diff --git a/README.md b/README.md index e89de64b..1e82bc5f 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ To ensure the installation or upgrade is successful, you can execute command `at ```text $ ate -V -ApiTestEngine version: 0.7.5 +ApiTestEngine version: 0.7.7 ``` Execute the command `ate -h` to view command help. @@ -98,9 +98,9 @@ And here is testset example of typical scenario: get `token` at the beginning, a app_version: $app_version json: sign: ${get_sign($user_agent, $device_sn, $os_platform, $app_version)} - extractors: + extract: - token: content.token - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} @@ -114,7 +114,7 @@ And here is testset example of typical scenario: get `token` at the beginning, a json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} ``` diff --git a/ate/__init__.py b/ate/__init__.py index ed4e820f..7adfc4e4 100644 --- a/ate/__init__.py +++ b/ate/__init__.py @@ -1 +1 @@ -__version__ = '0.7.5' \ No newline at end of file +__version__ = '0.7.7' \ No newline at end of file diff --git a/ate/client.py b/ate/client.py index de2685ca..26b7d9fa 100644 --- a/ate/client.py +++ b/ate/client.py @@ -54,7 +54,7 @@ class HttpSession(requests.Session): else: raise ParamsError("base url missed!") - def request(self, method, url, **kwargs): + def request(self, method, url, name=None, **kwargs): """ Constructs and sends a :py:class:`requests.Request`. Returns :py:class:`requests.Response` object. @@ -63,6 +63,8 @@ class HttpSession(requests.Session): method for the new :class:`Request` object. :param url: URL for the new :class:`Request` object. + :param name: (optional) + Placeholder, make compatible with Locust's HttpSession :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`. :param data: (optional) diff --git a/ate/context.py b/ate/context.py index 3c809930..cda6c5a3 100644 --- a/ate/context.py +++ b/ate/context.py @@ -34,7 +34,7 @@ class Context(object): self.testcase_variables_mapping = copy.deepcopy(self.testset_shared_variables_mapping) self.testcase_parser.bind_functions(self.testcase_functions_config) - self.testcase_parser.bind_variables(self.testcase_variables_mapping) + self.testcase_parser.update_binded_variables(self.testcase_variables_mapping) if level == "testset": self.import_module_items(["ate.built_in"], "testset") @@ -117,7 +117,17 @@ class Context(object): self.testset_shared_variables_mapping[variable_name] = variable_evale_value self.testcase_variables_mapping[variable_name] = variable_evale_value - self.testcase_parser.bind_variables(self.testcase_variables_mapping) + self.testcase_parser.update_binded_variables(self.testcase_variables_mapping) + + def bind_extracted_variables(self, variables): + """ bind extracted variables to testset context + @param (OrderDict) variables + extracted value do not need to evaluate. + """ + for variable_name, value in variables.items(): + self.testset_shared_variables_mapping[variable_name] = value + self.testcase_variables_mapping[variable_name] = value + self.testcase_parser.update_binded_variables(self.testcase_variables_mapping) def __update_context_functions_config(self, level, config_mapping): """ diff --git a/ate/locustfile_template b/ate/locustfile_template index 10f53d43..e1ebbdb2 100644 --- a/ate/locustfile_template +++ b/ate/locustfile_template @@ -1,6 +1,5 @@ #coding: utf-8 import zmq -import os from locust import HttpLocust, TaskSet, task from ate import runner, exception diff --git a/ate/response.py b/ate/response.py index 933ae25b..b7013a75 100644 --- a/ate/response.py +++ b/ate/response.py @@ -1,6 +1,11 @@ +import logging +import re from collections import OrderedDict from ate import exception, utils +from requests.structures import CaseInsensitiveDict + +text_extractor_regexp_compile = re.compile(r".*\(.*\).*") class ResponseObject(object): @@ -10,23 +15,45 @@ class ResponseObject(object): @param (requests.Response instance) resp_obj """ self.resp_obj = resp_obj + self.resp_text = resp_obj.text + self.resp_body = self.parsed_body() def parsed_body(self): try: return self.resp_obj.json() except ValueError: - return self.resp_obj.text + return self.resp_text def parsed_dict(self): return { 'status_code': self.resp_obj.status_code, 'headers': self.resp_obj.headers, - 'body': self.parsed_body() + 'body': self.resp_body } - def extract_field(self, field, delimiter='.'): - """ extract field from requests.Response - @param (str) field of requests.Response object, and may be joined by delimiter + def _extract_field_with_regex(self, field): + """ extract field from response content with regex. + requests.Response body could be json or html text. + @param (str) field should only be regex string that matched r".*\(.*\).*" + e.g. + self.resp_text: "LB123abcRB789" + field: "LB[\d]*(.*)RB[\d]*" + return: abc + """ + matched = re.search(field, self.resp_text) + if not matched: + err_msg = "Extractor error: failed to extract data with regex!\n" + err_msg += "response body: {}\n".format(self.resp_text) + err_msg += "regex: {}\n".format(field) + logging.error(err_msg) + raise exception.ParamsError(err_msg) + + return matched.group(1) + + def _extract_field_with_delimiter(self, field): + """ response content could be json or html text. + @param (str) field should be string joined by delimiter. + e.g. "status_code" "content" "headers.content-type" @@ -36,28 +63,47 @@ class ResponseObject(object): # string.split(sep=None, maxsplit=-1) -> list of strings # e.g. "content.person.name" => ["content", "person.name"] try: - top_query, sub_query = field.split(delimiter, 1) + top_query, sub_query = field.split('.', 1) except ValueError: top_query = field sub_query = None if top_query in ["body", "content", "text"]: - json_content = self.parsed_body() + top_query_content = self.parsed_body() else: - json_content = getattr(self.resp_obj, top_query) + top_query_content = getattr(self.resp_obj, top_query) if sub_query: + if not isinstance(top_query_content, (dict, CaseInsensitiveDict, list)): + err_msg = "Extractor error: failed to extract data with regex!\n" + err_msg += "response: {}\n".format(self.parsed_dict()) + err_msg += "regex: {}\n".format(field) + logging.error(err_msg) + raise exception.ParamsError(err_msg) + # e.g. key: resp_headers_content_type, sub_query = "content-type" - return utils.query_json(json_content, sub_query) + return utils.query_json(top_query_content, sub_query) else: # e.g. key: resp_status_code, resp_content - return json_content + return top_query_content except AttributeError: - raise exception.ParseResponseError("failed to extract bind variable in response!") + err_msg = "Failed to extract value from response!\n" + err_msg += "response: {}\n".format(self.parsed_dict()) + err_msg += "extract field field: {}\n".format(field) + logging.error(err_msg) + raise exception.ParamsError(err_msg) + + def extract_field(self, field): + """ extract value from requests.Response. + """ + if text_extractor_regexp_compile.match(field): + return self._extract_field_with_regex(field) + else: + return self._extract_field_with_delimiter(field) def extract_response(self, extractors): - """ extract content from requests.Response + """ extract value from requests.Response and store in OrderedDict. @param (list) extractors [ {"resp_status_code": "status_code"}, diff --git a/ate/runner.py b/ate/runner.py index b84e9206..7c80de96 100644 --- a/ate/runner.py +++ b/ate/runner.py @@ -1,3 +1,4 @@ +import logging from collections import OrderedDict from ate import exception, response, testcase, utils @@ -84,8 +85,8 @@ class Runner(object): }, "body": '{"name": "user", "password": "123456"}' }, - "extractors": [], # optional - "validators": [], # optional + "extract": [], # optional + "validate": [], # optional "setup": [], # optional "teardown": [] # optional } @@ -96,14 +97,16 @@ class Runner(object): try: url = parsed_request.pop('url') method = parsed_request.pop('method') + group_name = parsed_request.pop("group", None) except KeyError: raise exception.ParamsError("URL or METHOD missed!") run_times = int(testcase.get("times", 1)) - extractors = testcase.get("extractors") \ - or testcase.get("extractor") \ + extractors = testcase.get("extract") \ + or testcase.get("extractors") \ or testcase.get("extract_binds", []) - validators = testcase.get("validators", []) + validators = testcase.get("validate") \ + or testcase.get("validators", []) setup_actions = testcase.get("setup", []) teardown_actions = testcase.get("teardown", []) @@ -114,13 +117,24 @@ class Runner(object): for _ in range(run_times): setup_teardown(setup_actions) - resp = self.http_client_session.request(url=url, method=method, **parsed_request) + resp = self.http_client_session.request( + method, + url, + name=group_name, + **parsed_request + ) resp_obj = response.ResponseObject(resp) extracted_variables_mapping = resp_obj.extract_response(extractors) - self.context.bind_variables(extracted_variables_mapping, level="testset") + self.context.bind_extracted_variables(extracted_variables_mapping) - resp_obj.validate(validators, self.context.get_testcase_variables_mapping()) + try: + resp_obj.validate(validators, self.context.get_testcase_variables_mapping()) + except (exception.ParamsError, exception.ResponseError, exception.ValidationError): + logging.error("Exception occured.") + logging.error("HTTP request kwargs: \n{}".format(parsed_request)) + logging.error("HTTP response content: \n{}".format(resp.text)) + raise setup_teardown(teardown_actions) @@ -144,8 +158,8 @@ class Runner(object): "name": "testcase description", "variables": [], # optional, override "request": {}, - "extractors": {}, # optional - "validators": {} # optional + "extract": {}, # optional + "validate": {} # optional }, testcase12 ] diff --git a/ate/testcase.py b/ate/testcase.py index c060e541..34a02725 100644 --- a/ate/testcase.py +++ b/ate/testcase.py @@ -330,11 +330,11 @@ def substitute_variables_with_mapping(content, mapping): class TestcaseParser(object): def __init__(self, variables={}, functions={}, file_path=None): - self.bind_variables(variables) + self.update_binded_variables(variables) self.bind_functions(functions) self.file_path = file_path - def bind_variables(self, variables): + def update_binded_variables(self, variables): """ bind variables to current testcase parser @param (dict) variables, variables binds mapping { diff --git a/docs/extraction-and-validation.md b/docs/extraction-and-validation.md index 0cb76fc0..0e380f3c 100644 --- a/docs/extraction-and-validation.md +++ b/docs/extraction-and-validation.md @@ -24,7 +24,7 @@ Suppose we get the following HTTP response. } ``` -In `extractors` and `validators`, we can do chain operation to extract data field in HTTP response. +In `extract` and `validate`, we can do chain operation to extract data field in HTTP response. For instance, if we want to get `Content-Type` in response headers, then we can specify `headers.content-type`; if we want to get `first_name` in response content, we can specify `content.person.name.first_name`. @@ -46,10 +46,10 @@ content.person.cities.1 ``` ```yaml -extractors: +extract: - content_type: headers.content-type - first_name: content.person.name.first_name -validators: +validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "headers.content-type", "expected": "application/json"} - {"check": "headers.content-length", "comparator": "gt", "expected": 40} diff --git a/docs/quickstart.md b/docs/quickstart.md index f1756da9..c6b2783b 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -65,7 +65,7 @@ Open your favorite text editor and you can write test cases like this. json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} ``` @@ -120,9 +120,9 @@ To fix this problem, we should correlate `token` field in the second API test ca app_version: 2.8.6 json: sign: 19067cf712265eb5426db8d3664026c1ccea02b9 - extractors: + extract: - token: content.token - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} @@ -137,12 +137,12 @@ To fix this problem, we should correlate `token` field in the second API test ca json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} ``` -As you see, the `token` field is no longer hardcoded, instead it is extracted from the first API request with `extractors` mechanism. In the meanwhile, it is assigned to `token` variable, which can be referenced by the subsequent API requests. +As you see, the `token` field is no longer hardcoded, instead it is extracted from the first API request with `extract` mechanism. In the meanwhile, it is assigned to `token` variable, which can be referenced by the subsequent API requests. Now we save the test cases to [`quickstart-demo-rev-1.yml`][quickstart-demo-rev-1] and rerun it, and we will find that both API requests to be successful. @@ -202,9 +202,9 @@ And then, we can revise our demo test case and reference the functions. Suppose app_version: $app_version json: sign: ${get_sign($user_agent, $device_sn, $os_platform, $app_version)} - extractors: + extract: - token: content.token - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} @@ -219,7 +219,7 @@ And then, we can revise our demo test case and reference the functions. Suppose json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} ``` @@ -266,9 +266,9 @@ To handle this case, overall `config` block is supported in `ApiTestEngine`. If app_version: $app_version json: sign: ${get_sign($user_agent, $device_sn, $os_platform, $app_version)} - extractors: + extract: - token: content.token - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} @@ -282,7 +282,7 @@ To handle this case, overall `config` block is supported in `ApiTestEngine`. If json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} ``` diff --git a/examples/quickstart-demo-rev-0.yml b/examples/quickstart-demo-rev-0.yml index 1080d5eb..5580b17d 100644 --- a/examples/quickstart-demo-rev-0.yml +++ b/examples/quickstart-demo-rev-0.yml @@ -10,7 +10,7 @@ app_version: 2.8.6 json: sign: 19067cf712265eb5426db8d3664026c1ccea02b9 - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} @@ -25,6 +25,6 @@ json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} diff --git a/examples/quickstart-demo-rev-1.yml b/examples/quickstart-demo-rev-1.yml index d203cf8a..0610615a 100644 --- a/examples/quickstart-demo-rev-1.yml +++ b/examples/quickstart-demo-rev-1.yml @@ -10,9 +10,9 @@ app_version: 2.8.6 json: sign: 19067cf712265eb5426db8d3664026c1ccea02b9 - extractors: + extract: - token: content.token - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} @@ -27,6 +27,6 @@ json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} diff --git a/examples/quickstart-demo-rev-2.yml b/examples/quickstart-demo-rev-2.yml index 7b2282f8..c41a37f8 100644 --- a/examples/quickstart-demo-rev-2.yml +++ b/examples/quickstart-demo-rev-2.yml @@ -15,9 +15,9 @@ app_version: $app_version json: sign: ${get_sign($user_agent, $device_sn, $os_platform, $app_version)} - extractors: + extract: - token: content.token - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} @@ -32,6 +32,6 @@ json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} \ No newline at end of file diff --git a/examples/quickstart-demo-rev-3.yml b/examples/quickstart-demo-rev-3.yml index cb937011..952d2a59 100644 --- a/examples/quickstart-demo-rev-3.yml +++ b/examples/quickstart-demo-rev-3.yml @@ -22,9 +22,9 @@ app_version: $app_version json: sign: ${get_sign($user_agent, $device_sn, $os_platform, $app_version)} - extractors: + extract: - token: content.token - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} @@ -38,6 +38,6 @@ json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} diff --git a/tests/api/demo.yml b/tests/api/demo.yml index ee752e39..d256bc68 100644 --- a/tests/api/demo.yml +++ b/tests/api/demo.yml @@ -10,7 +10,7 @@ app_version: $app_version json: sign: ${get_sign($user_agent, $device_sn, $os_platform, $app_version)} - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} diff --git a/tests/data/demo_testset_hardcode.json b/tests/data/demo_testset_hardcode.json index bd154933..08d72261 100644 --- a/tests/data/demo_testset_hardcode.json +++ b/tests/data/demo_testset_hardcode.json @@ -16,12 +16,12 @@ "sign": "f1219719911caae89ccc301679857ebfda115ca2" } }, - "extractors": [ + "extract": [ { "token": "content.token" } ], - "validators": [ + "validate": [ {"check": "status_code", "comparator": "eq", "expected": 200}, {"check": "content.token", "comparator": "len_eq", "expected": 16} ] @@ -43,7 +43,7 @@ "password": "123456" } }, - "validators": [ + "validate": [ {"check": "status_code", "comparator": "eq", "expected": 201}, {"check": "content.success", "comparator": "eq", "expected": true} ] @@ -65,7 +65,7 @@ "password": "123456" } }, - "validators": [ + "validate": [ {"check": "status_code", "comparator": "eq", "expected": 500}, {"check": "content.success", "comparator": "eq", "expected": false} ] diff --git a/tests/data/demo_testset_hardcode.yml b/tests/data/demo_testset_hardcode.yml index 2b112e36..7646e86f 100644 --- a/tests/data/demo_testset_hardcode.yml +++ b/tests/data/demo_testset_hardcode.yml @@ -11,9 +11,9 @@ app_version: '2.8.6' json: sign: f1219719911caae89ccc301679857ebfda115ca2 - extractors: + extract: - token: content.token - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} @@ -29,7 +29,7 @@ json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} @@ -45,6 +45,6 @@ json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 500} - {"check": "content.success", "comparator": "eq", "expected": false} \ No newline at end of file diff --git a/tests/data/demo_testset_layer.yml b/tests/data/demo_testset_layer.yml index 44102750..50328b6f 100644 --- a/tests/data/demo_testset_layer.yml +++ b/tests/data/demo_testset_layer.yml @@ -16,20 +16,20 @@ - test: name: get token api: get_token($user_agent, $device_sn, $os_platform, $app_version) - extractors: + extract: - token: content.token - test: name: reset all users api: reset_all($token) - validators: + validate: - {"check": "status_code", "expected": 200} - {"check": "content.success", "expected": true} - test: name: get user that does not exist api: get_user(1000, $token) - validators: + validate: - {"check": "status_code", "expected": 404} - {"check": "content.success", "expected": false} @@ -39,14 +39,14 @@ - user_name: "user1" - user_password: "123456" api: create_user(1000, $user_name, $user_password, $token) - validators: + validate: - {"check": "status_code", "expected": 201} - {"check": "content.success", "expected": true} - test: name: get user that has been created api: get_user(1000, $token) - validators: + validate: - {"check": "status_code", "expected": 200} - {"check": "content.success", "expected": true} - {"check": "content.data.password", "expected": "123456"} @@ -57,7 +57,7 @@ - user_name: "user1" - user_password: "123456" api: create_user(1000, $user_name, $user_password, $token) - validators: + validate: - {"check": "status_code", "expected": 500} - {"check": "content.success", "expected": false} @@ -67,14 +67,14 @@ - user_name: "user1" - user_password: "654321" api: update_user(1000, $user_name, $user_password, $token) - validators: + validate: - {"check": "status_code", "expected": 200} - {"check": "content.success", "expected": true} - test: name: get user that has been updated api: get_user(1000, $token) - validators: + validate: - {"check": "status_code", "expected": 200} - {"check": "content.success", "expected": true} - {"check": "content.data.password", "expected": "654321"} @@ -82,21 +82,21 @@ - test: name: get users api: get_users($token) - validators: + validate: - {"check": "status_code", "expected": 200} - {"check": "content.count", "expected": 1} - test: name: delete user that exists api: delete_user(1000, $token) - validators: + validate: - {"check": "status_code", "expected": 200} - {"check": "content.success", "expected": true} - test: name: get users api: get_users($token) - validators: + validate: - {"check": "status_code", "expected": 200} - {"check": "content.count", "expected": 0} @@ -106,13 +106,13 @@ - user_name: "user1" - user_password: "123456" api: create_user(1000, $user_name, $user_password, $token) - validators: + validate: - {"check": "status_code", "expected": 201} - {"check": "content.success", "expected": true} - test: name: get users api: get_users($token) - validators: + validate: - {"check": "status_code", "expected": 200} - {"check": "content.count", "expected": 1} diff --git a/tests/data/demo_testset_template_import_functions.yml b/tests/data/demo_testset_template_import_functions.yml index fc710cf8..d786ecdf 100644 --- a/tests/data/demo_testset_template_import_functions.yml +++ b/tests/data/demo_testset_template_import_functions.yml @@ -25,9 +25,9 @@ app_version: $app_version json: sign: ${get_sign($user_agent, $device_sn, $os_platform, $app_version)} - extractors: + extract: - token: content.token - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} @@ -44,7 +44,7 @@ json: name: $user_name password: $user_password - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} @@ -58,6 +58,6 @@ json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 500} - {"check": "content.success", "comparator": "eq", "expected": false} diff --git a/tests/data/demo_testset_template_lambda_functions.yml b/tests/data/demo_testset_template_lambda_functions.yml index 7e450aa6..98321784 100644 --- a/tests/data/demo_testset_template_lambda_functions.yml +++ b/tests/data/demo_testset_template_lambda_functions.yml @@ -35,9 +35,9 @@ app_version: $app_version json: sign: ${get_sign_lambda($user_agent, $device_sn, $os_platform, $app_version)} - extractors: + extract: - token: content.token - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} @@ -54,7 +54,7 @@ json: name: $user_name password: $user_password - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} @@ -68,6 +68,6 @@ json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 500} - {"check": "content.success", "comparator": "eq", "expected": false} diff --git a/tests/data/demo_testset_variables.yml b/tests/data/demo_testset_variables.yml index 56e31fd6..1efd6bb9 100644 --- a/tests/data/demo_testset_variables.yml +++ b/tests/data/demo_testset_variables.yml @@ -26,9 +26,9 @@ app_version: $app_version json: sign: $sign - extractors: + extract: - token: content.token - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 200} - {"check": "content.token", "comparator": "len_eq", "expected": 16} @@ -45,7 +45,7 @@ json: name: $user_name password: $user_password - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 201} - {"check": "content.success", "comparator": "eq", "expected": true} @@ -59,6 +59,6 @@ json: name: "user1" password: "123456" - validators: + validate: - {"check": "status_code", "comparator": "eq", "expected": 500} - {"check": "content.success", "comparator": "eq", "expected": false} diff --git a/tests/test_response.py b/tests/test_response.py index 94874571..cce3aca8 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -149,6 +149,55 @@ class TestResponse(ApiServerUnittest): "abc" ) + def test_extract_text_response(self): + resp = requests.post( + url="http://127.0.0.1:5000/customize-response", + json={ + 'headers': { + 'Content-Type': "application/json" + }, + 'body': "LB123abcRB789" + } + ) + + extract_binds_list = [ + {"resp_content_key1": "LB123(.*)RB789"}, + {"resp_content_key2": "LB[\d]*(.*)RB[\d]*"}, + {"resp_content_key3": "LB[\d]*(.*)9"} + ] + resp_obj = response.ResponseObject(resp) + + extract_binds_dict = resp_obj.extract_response(extract_binds_list) + self.assertEqual( + extract_binds_dict["resp_content_key1"], + "abc" + ) + self.assertEqual( + extract_binds_dict["resp_content_key2"], + "abc" + ) + self.assertEqual( + extract_binds_dict["resp_content_key3"], + "abcRB78" + ) + + def test_extract_text_response_exception(self): + resp = requests.post( + url="http://127.0.0.1:5000/customize-response", + json={ + 'headers': { + 'Content-Type': "application/json" + }, + 'body': "LB123abcRB789" + } + ) + extract_binds_list = [ + {"resp_content_key1": "LB123.*RB789"} + ] + resp_obj = response.ResponseObject(resp) + with self.assertRaises(exception.ParamsError): + resp_obj.extract_response(extract_binds_list) + def test_extract_response_empty(self): resp = requests.post( url="http://127.0.0.1:5000/customize-response", @@ -174,7 +223,7 @@ class TestResponse(ApiServerUnittest): {"resp_content_body": "content.abc"} ] resp_obj = response.ResponseObject(resp) - with self.assertRaises(exception.ResponseError): + with self.assertRaises(exception.ParamsError): resp_obj.extract_response(extract_binds_list) def test_validate(self): diff --git a/tests/test_runner.py b/tests/test_runner.py index 9996d25a..006d7256 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -53,10 +53,10 @@ class TestRunner(ApiServerUnittest): "sign": "f1219719911caae89ccc301679857ebfda115ca2" } }, - "extractors": [ + "extract": [ {"token": "content.token"} ], - "validators": [ + "validate": [ {"check": "status_code", "comparator": "eq", "expected": 205}, {"check": "content.token", "comparator": "len_eq", "expected": 19} ] diff --git a/tests/test_testcase.py b/tests/test_testcase.py index 0ef35482..5b7ffdf5 100644 --- a/tests/test_testcase.py +++ b/tests/test_testcase.py @@ -421,7 +421,7 @@ class TestcaseParserUnittest(unittest.TestCase): self.assertIn("request", testsets_list[0]["config"]) self.assertIn("request", testsets_list[0]["testcases"][0]) self.assertIn("url", testsets_list[0]["testcases"][0]["request"]) - self.assertIn("validators", testsets_list[0]["testcases"][0]) + self.assertIn("validate", testsets_list[0]["testcases"][0]) def test_substitute_variables_with_mapping(self): content = {