From bfb9b1e3e1dc5cfa26caa34e694d54badf0b7eca Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 23 Apr 2018 16:05:31 +0800 Subject: [PATCH] merge_validator: support checking unhashable values such as dict --- httprunner/__about__.py | 2 +- httprunner/context.py | 7 +++--- httprunner/response.py | 2 +- httprunner/testcase.py | 42 +++++++++++++++++++++++-------- tests/api/demo.yml | 1 + tests/data/demo_testset_layer.yml | 1 + tests/test_testcase.py | 14 +++++++++++ 7 files changed, 53 insertions(+), 16 deletions(-) diff --git a/httprunner/__about__.py b/httprunner/__about__.py index 580a87d6..d3313ffd 100644 --- a/httprunner/__about__.py +++ b/httprunner/__about__.py @@ -1,7 +1,7 @@ __title__ = 'HttpRunner' __description__ = 'One-stop solution for HTTP(S) testing.' __url__ = 'https://github.com/HttpRunner/HttpRunner' -__version__ = '1.3.10' +__version__ = '1.3.11' __author__ = 'debugtalk' __author_email__ = 'mail@debugtalk.com' __license__ = 'MIT' diff --git a/httprunner/context.py b/httprunner/context.py index 27102242..a131a60f 100644 --- a/httprunner/context.py +++ b/httprunner/context.py @@ -184,12 +184,13 @@ class Context(object): } """ check_item = validator["check"] - # check_item should only be in 3 types: + # check_item should only be in 4 types: # 1, variable reference, e.g. $token # 2, string joined by delimiter. e.g. "status_code", "headers.content-type" # 3, regex string, e.g. "LB[\d]*(.*)RB[\d]*" - if testcase.extract_variables(check_item): - # type 1 + # 4, dict or list, maybe containing variables reference, e.g. {"var": "$abc"} + if isinstance(check_item, (dict, list)) or testcase.extract_variables(check_item): + # type 4 or type 1 check_value = self.eval_content(check_item) else: try: diff --git a/httprunner/response.py b/httprunner/response.py index f4d2067c..565a3ab6 100644 --- a/httprunner/response.py +++ b/httprunner/response.py @@ -123,7 +123,7 @@ class ResponseObject(object): msg += "\t=> {}".format(value) logger.log_debug(msg) - except exception.ParseResponseError: + except (exception.ParseResponseError, TypeError): logger.log_error("failed to extract field: {}".format(field)) raise diff --git a/httprunner/testcase.py b/httprunner/testcase.py index 29fc4acb..fc297f3a 100644 --- a/httprunner/testcase.py +++ b/httprunner/testcase.py @@ -1,6 +1,7 @@ # encoding: utf-8 import ast +import collections import csv import io import itertools @@ -300,6 +301,34 @@ def parse_validator(validator): "comparator": comparator } +def _get_validators_mapping(validators): + """ get validators mapping from api or test validators + @param (list) validators: + [ + {"check": "v1", "expect": 201, "comparator": "eq"}, + {"check": {"b": 1}, "expect": 200, "comparator": "eq"} + ] + @return + { + ("v1", "eq"): {"check": "v1", "expect": 201, "comparator": "eq"}, + ('{"b": 1}', "eq"): {"check": {"b": 1}, "expect": 200, "comparator": "eq"} + } + """ + validators_mapping = {} + + for validator in validators: + validator = parse_validator(validator) + + if not isinstance(validator["check"], collections.Hashable): + check = json.dumps(validator["check"]) + else: + check = validator["check"] + + key = (check, validator["comparator"]) + validators_mapping[key] = validator + + return validators_mapping + def merge_validator(api_validators, test_validators): """ merge api_validators with test_validators @params: @@ -319,17 +348,8 @@ def merge_validator(api_validators, test_validators): return api_validators else: - api_validators_mapping = {} - for api_validator in api_validators: - api_validator = parse_validator(api_validator) - key = (api_validator["check"], api_validator["comparator"]) - api_validators_mapping[key] = api_validator - - test_validators_mapping = {} - for test_validator in test_validators: - test_validator = parse_validator(test_validator) - key = (test_validator["check"], test_validator["comparator"]) - test_validators_mapping[key] = test_validator + api_validators_mapping = _get_validators_mapping(api_validators) + test_validators_mapping = _get_validators_mapping(test_validators) api_validators_mapping.update(test_validators_mapping) return list(api_validators_mapping.values()) diff --git a/tests/api/demo.yml b/tests/api/demo.yml index 5ae3c733..ee95575e 100644 --- a/tests/api/demo.yml +++ b/tests/api/demo.yml @@ -13,6 +13,7 @@ validate: - "eq": ["status_code", 0] - "len_eq": ["content.token", 12] + - "contains": [{"a": 1, "b": 2}, "a"] - api: def: create_user($uid, $user_name, $user_password, $token) diff --git a/tests/data/demo_testset_layer.yml b/tests/data/demo_testset_layer.yml index 61723722..9d314be9 100644 --- a/tests/data/demo_testset_layer.yml +++ b/tests/data/demo_testset_layer.yml @@ -21,6 +21,7 @@ validate: - "eq": ["status_code", 200] - "len_eq": ["content.token", 16] + - "contains": [{"a": 1, "b": 2}, "b"] - test: name: reset all users diff --git a/tests/test_testcase.py b/tests/test_testcase.py index a7912bd5..3e401324 100644 --- a/tests/test_testcase.py +++ b/tests/test_testcase.py @@ -721,6 +721,20 @@ class TestcaseParserUnittest(unittest.TestCase): merged_validators ) + def test_merge_validator_with_dict(self): + api_validators = [ + {'eq': ["a", {"v": 1}]}, + {'eq': [{"b": 1}, 200]} + ] + test_validators = [ + {'len_eq': ['s3', 12]}, + {'eq': [{"b": 1}, 201]} + ] + + merged_validators = testcase.merge_validator(api_validators, test_validators) + self.assertEqual(len(merged_validators), 3) + self.assertEqual(merged_validators[1], {'check': {'b': 1}, 'expect': 201, 'comparator': 'eq'}) + def test_merge_extractor(self): api_extrators = [{"var1": "val1"}, {"var2": "val2"}] test_extracors = [{"var1": "val111"}, {"var3": "val3"}]