diff --git a/httprunner/context.py b/httprunner/context.py index 26f65c38..8d2cefe0 100644 --- a/httprunner/context.py +++ b/httprunner/context.py @@ -4,7 +4,7 @@ import re import sys from collections import OrderedDict -from httprunner import utils +from httprunner import exception, utils from httprunner.testcase import TestcaseParser @@ -165,10 +165,47 @@ class Context(object): def get_testcase_variables_mapping(self): return self.testcase_variables_mapping - def get_testcase_functions_mapping(self): - return self.testcase_functions_config - def exec_content_functions(self, content): """ execute functions in content. """ self.testcase_parser.eval_content_functions(content) + + def do_validation(self, validator_dict): + """ validate with functions + """ + comparator = utils.get_uniform_comparator(validator_dict["comparator"]) + validate_func = self.testcase_parser.get_bind_item("function", comparator) + + if not validate_func: + raise exception.FunctionNotFound("comparator not found: {}".format(comparator)) + + check_item = validator_dict["check_item"] + check_value = validator_dict["check_value"] + expect_value = validator_dict["expect_value"] + + try: + if check_value is None or expect_value is None: + assert comparator in ["is", "eq", "equals", "=="] + + validate_func(validator_dict["check_value"], validator_dict["expect_value"]) + except (AssertionError, TypeError): + err_msg = "\n" + "\n".join([ + "\tcheck item name: %s;" % check_item, + "\tcheck item value: %s (%s);" % (check_value, type(check_value).__name__), + "\tcomparator: %s;" % comparator, + "\texpected value: %s (%s)." % (expect_value, type(expect_value).__name__) + ]) + raise exception.ValidationError(err_msg) + + def validate(self, validators, resp_obj): + """ check validators with the context variable mapping. + @param (list) validators + @param (object) resp_obj + """ + variables_mapping = self.get_testcase_variables_mapping() + + for validator in validators: + validator_dict = resp_obj.parse_validator(validator, variables_mapping) + self.do_validation(validator_dict) + + return True diff --git a/httprunner/response.py b/httprunner/response.py index 586d9e67..b6ed2a6d 100644 --- a/httprunner/response.py +++ b/httprunner/response.py @@ -189,39 +189,3 @@ class ResponseObject(object): "comparator": comparator } return validator_dict - - def do_validation(self, validator_dict, functions_mapping): - """ validate with functions - """ - comparator = utils.get_uniform_comparator(validator_dict["comparator"]) - - validate_func = functions_mapping.get(comparator) - if not validate_func: - raise exception.FunctionNotFound("comparator not found: {}".format(comparator)) - - check_item = validator_dict["check_item"] - check_value = validator_dict["check_value"] - expect_value = validator_dict["expect_value"] - - try: - if check_value is None or expect_value is None: - assert comparator in ["is", "eq", "equals", "=="] - - validate_func(validator_dict["check_value"], validator_dict["expect_value"]) - except (AssertionError, TypeError): - err_msg = "\n" + "\n".join([ - "\tcheck item name: %s;" % check_item, - "\tcheck item value: %s (%s);" % (check_value, type(check_value).__name__), - "\tcomparator: %s;" % comparator, - "\texpected value: %s (%s)." % (expect_value, type(expect_value).__name__) - ]) - raise exception.ValidationError(err_msg) - - def validate(self, validators, variables_mapping, functions_mapping): - """ check validators with the context variable mapping. - """ - for validator in validators: - validator_dict = self.parse_validator(validator, variables_mapping) - self.do_validation(validator_dict, functions_mapping) - - return True diff --git a/httprunner/runner.py b/httprunner/runner.py index ad6bca77..603da4e3 100644 --- a/httprunner/runner.py +++ b/httprunner/runner.py @@ -129,11 +129,7 @@ class Runner(object): self.context.bind_extracted_variables(extracted_variables_mapping) try: - resp_obj.validate( - validators, - self.context.get_testcase_variables_mapping(), - self.context.get_testcase_functions_mapping() - ) + self.context.validate(validators, resp_obj) except (exception.ParamsError, exception.ResponseError, exception.ValidationError): err_msg = u"Exception occured.\n" err_msg += u"HTTP request url: {}\n".format(url) diff --git a/tests/data/debugtalk.py b/tests/data/debugtalk.py index 491e4103..1c5d1889 100644 --- a/tests/data/debugtalk.py +++ b/tests/data/debugtalk.py @@ -30,3 +30,13 @@ get_sign_lambda = lambda *args: hmac.new( def gen_md5(*args): return hashlib.md5("".join(args).encode('utf-8')).hexdigest() + +def sum_status_code(status_code, expect_sum): + """ sum status code digits + e.g. 400 => 4, 201 => 3 + """ + sum_value = 0 + for digit in str(status_code): + sum_value += int(digit) + + assert sum_value == expect_sum diff --git a/tests/data/demo_testset_hardcode.json b/tests/data/demo_testset_hardcode.json index d0ae92b7..1dbd8c94 100644 --- a/tests/data/demo_testset_hardcode.json +++ b/tests/data/demo_testset_hardcode.json @@ -25,6 +25,7 @@ {"eq": ["status_code", 200]}, {"len_eq": ["content.token", 16]}, {"check": "status_code", "comparator": "eq", "expect": 200}, + {"sum_status_code": ["status_code", 2]}, {"check": "content.token", "comparator": "len_eq", "expect": 16} ] } @@ -49,6 +50,7 @@ {"eq": ["status_code", 201]}, {"eq": ["content.success", true]}, {"check": "status_code", "comparator": "eq", "expect": 201}, + {"sum_status_code": ["status_code", 3]}, {"check": "content.success", "comparator": "eq", "expect": true} ] } @@ -73,6 +75,7 @@ {"eq": ["status_code", 500]}, {"eq": ["content.success", false]}, {"check": "status_code", "comparator": "eq", "expect": 500}, + {"sum_status_code": ["status_code", 5]}, {"check": "content.success", "comparator": "eq", "expect": false} ] } diff --git a/tests/data/demo_testset_hardcode.yml b/tests/data/demo_testset_hardcode.yml index c22627ac..d16543de 100644 --- a/tests/data/demo_testset_hardcode.yml +++ b/tests/data/demo_testset_hardcode.yml @@ -15,9 +15,11 @@ - token: content.token validate: - eq: ["status_code", 200] + - len_eq: ["token", 16] - len_eq: ["content.token", 16] - {"check": "status_code", "comparator": "eq", "expect": 200} - - {"check": "content.token", "comparator": "len_eq", "expect": 16} + - sum_status_code: ["status_code", 2] + - {"check": "token", "comparator": "len_eq", "expect": 16} - test: name: create user which does not exist @@ -33,6 +35,7 @@ password: "123456" validate: - eq: ["status_code", 201] + - sum_status_code: ["status_code", 3] - eq: ["content.success", True] - {"check": "status_code", "comparator": "eq", "expect": 201} - {"check": "content.success", "comparator": "eq", "expect": true} @@ -51,6 +54,7 @@ password: "123456" validate: - "eq": ["status_code", 500] + - sum_status_code: ["status_code", 5] - "eq": ["content.success", false] - {"check": "status_code", "comparator": "eq", "expect": 500} - {"check": "content.success", "comparator": "eq", "expect": false} \ No newline at end of file diff --git a/tests/test_context.py b/tests/test_context.py index 413654d3..a75051b4 100644 --- a/tests/test_context.py +++ b/tests/test_context.py @@ -1,13 +1,13 @@ import os import time -import unittest -from httprunner import runner, testcase, utils +import requests +from httprunner import exception, response, runner, testcase, utils from httprunner.context import Context -from httprunner.exception import ParamsError +from tests.base import ApiServerUnittest -class VariableBindsUnittest(unittest.TestCase): +class VariableBindsUnittest(ApiServerUnittest): def setUp(self): self.context = Context() @@ -217,3 +217,72 @@ class VariableBindsUnittest(unittest.TestCase): end_time = time.time() elapsed_time = end_time - start_time self.assertGreater(elapsed_time, 1) + + def test_do_validation(self): + self.context.do_validation( + {"check_item": "check_item", "check_value": 1, "expect_value": 1, "comparator": "eq"} + ) + self.context.do_validation( + {"check_item": "check_item", "check_value": "abc", "expect_value": "abc", "comparator": "=="} + ) + + config_dict = { + "path": 'tests/data/demo_testset_hardcode.yml' + } + self.context.config_context(config_dict, "testset") + self.context.do_validation( + {"check_item": "status_code", "check_value": "201", "expect_value": 3, "comparator": "sum_status_code"} + ) + + def test_validate(self): + url = "http://127.0.0.1:5000/" + resp = requests.get(url) + resp_obj = response.ResponseObject(resp) + + validators = [ + {"eq": ["resp_status_code", 201]}, + {"check": "resp_status_code", "comparator": "eq", "expect": 201}, + {"check": "resp_body_success", "comparator": "eq", "expect": True} + ] + variables = [ + {"resp_status_code": 200}, + {"resp_body_success": True} + ] + self.context.bind_variables(variables) + + with self.assertRaises(exception.ValidationError): + self.context.validate(validators, resp_obj) + + variables = [ + {"resp_status_code": 201}, + {"resp_body_success": True} + ] + self.context.bind_variables(variables) + + self.assertTrue(self.context.validate(validators, resp_obj)) + + def test_validate_exception(self): + url = "http://127.0.0.1:5000/" + resp = requests.get(url) + resp_obj = response.ResponseObject(resp) + + # expected value missed in validators + validators = [ + {"eq": ["resp_status_code", 201]}, + {"check": "resp_status_code", "comparator": "eq", "expect": 201}, + {"check": "resp_body_success", "comparator": "eq", "expect": True} + ] + variables = [] + self.context.bind_variables(variables) + + with self.assertRaises(exception.ParamsError): + self.context.validate(validators, resp_obj) + + # expected value missed in variables mapping + variables = [ + {"resp_status_code": 200} + ] + self.context.bind_variables(variables) + + with self.assertRaises(exception.ValidationError): + self.context.validate(validators, resp_obj) diff --git a/tests/test_response.py b/tests/test_response.py index 8fd97b04..cfa58789 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -230,70 +230,3 @@ class TestResponse(ApiServerUnittest): resp_obj = response.ResponseObject(resp) with self.assertRaises(exception.ParamsError): resp_obj.extract_response(extract_binds_list) - - def test_do_validation(self): - url = "http://127.0.0.1:5000/" - resp = requests.get(url) - resp_obj = response.ResponseObject(resp) - - resp_obj.do_validation( - {"check_item": "check_item", "check_value": 1, "expect_value": 1, "comparator": "eq"}, - self.functions_mapping - ) - resp_obj.do_validation( - {"check_item": "check_item", "check_value": "abc", "expect_value": "abc", "comparator": "=="}, - self.functions_mapping - ) - - def test_validate(self): - url = "http://127.0.0.1:5000/" - resp = requests.get(url) - resp_obj = response.ResponseObject(resp) - - validators = [ - {"check": "resp_status_code", "comparator": "eq", "expect": 201}, - {"check": "resp_body_success", "comparator": "eq", "expect": True} - ] - variables_mapping = { - "resp_status_code": 200, - "resp_body_success": True - } - - with self.assertRaises(exception.ValidationError): - resp_obj.validate(validators, variables_mapping, self.functions_mapping) - - validators = [ - {"check": "resp_status_code", "comparator": "eq", "expect": 201}, - {"check": "resp_body_success", "comparator": "eq", "expect": True} - ] - variables_mapping = { - "resp_status_code": 201, - "resp_body_success": True - } - - self.assertTrue(resp_obj.validate(validators, variables_mapping, self.functions_mapping)) - - def test_validate_exception(self): - url = "http://127.0.0.1:5000/" - resp = requests.get(url) - resp_obj = response.ResponseObject(resp) - - # expected value missed in validators - validators = [ - {"check": "status_code", "comparator": "eq", "expect": 201}, - {"check": "body_success", "comparator": "eq"} - ] - variables_mapping = {} - with self.assertRaises(exception.ValidationError): - resp_obj.validate(validators, variables_mapping, self.functions_mapping) - - # expected value missed in variables mapping - validators = [ - {"check": "resp_status_code", "comparator": "eq", "expect": 201}, - {"check": "body_success", "comparator": "eq"} - ] - variables_mapping = { - "resp_status_code": 200 - } - with self.assertRaises(exception.ValidationError): - resp_obj.validate(validators, variables_mapping, self.functions_mapping) diff --git a/tests/test_runner.py b/tests/test_runner.py index 6c45df2d..3382ee23 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -27,6 +27,12 @@ class TestRunner(ApiServerUnittest): def test_run_single_testcase(self): for testcase_file_path in self.testcase_file_path_list: testcases = testcase._load_file(testcase_file_path) + + config_dict = { + "path": testcase_file_path + } + self.test_runner.init_config(config_dict, "testset") + test = testcases[0]["test"] self.assertTrue(self.test_runner._run_test(test))