From b71a06e159728b849903d0f4c24ca7685fd821c8 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 21 Jan 2019 17:19:31 +0800 Subject: [PATCH 1/7] change log level of Variables --- HISTORY.md | 16 ++++++++++------ httprunner/__about__.py | 2 +- httprunner/utils.py | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index cff5d7a3..c7b87a02 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,15 +1,19 @@ # Release History -## 2.0.1 (2019.01.18) +## 2.0.2 (2019-01-21) + +- change log level of "Variables & Output" to INFO + +## 2.0.1 (2019-01-18) Bugfixes: -- override current teststep variables with former testcase output variables; -- make compatible with testcase name is empty; -- skip undefined variable when parsing string content; -- add request method in report. +- override current teststep variables with former testcase output variables +- make compatible with testcase name is empty +- skip undefined variable when parsing string content +- add back request method in report -## 2.0.0 (2019.01.01) +## 2.0.0 (2019-01-01) - Massive Refactor and Simplification - Redesign testcase structure diff --git a/httprunner/__about__.py b/httprunner/__about__.py index 774f7c60..4193ecce 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__ = '2.0.1' +__version__ = '2.0.2' __author__ = 'debugtalk' __author_email__ = 'mail@debugtalk.com' __license__ = 'Apache-2.0' diff --git a/httprunner/utils.py b/httprunner/utils.py index 4cfe6d2a..109cdb0b 100644 --- a/httprunner/utils.py +++ b/httprunner/utils.py @@ -512,7 +512,7 @@ def print_io(in_out): content += prepare_content("Out", _out) content += "-" * 56 + "\n" - logger.log_debug(content) + logger.log_info(content) def create_scaffold(project_name): From c73a708307fe21b5a89d1e43fabde45cdbb33833 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Tue, 22 Jan 2019 21:19:03 +0800 Subject: [PATCH 2/7] print Invalid testcase path or testcases --- httprunner/api.py | 2 +- httprunner/utils.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/httprunner/api.py b/httprunner/api.py index d0190388..43292e00 100644 --- a/httprunner/api.py +++ b/httprunner/api.py @@ -233,7 +233,7 @@ class HttpRunner(object): elif validator.is_testcases(path_or_tests): return self.run_tests(path_or_tests) else: - raise exceptions.ParamsError("invalid testcase path or testcases.") + raise exceptions.ParamsError("Invalid testcase path or testcases: {}".format(path_or_tests)) @property def summary(self): diff --git a/httprunner/utils.py b/httprunner/utils.py index 109cdb0b..e9ba70f3 100644 --- a/httprunner/utils.py +++ b/httprunner/utils.py @@ -512,7 +512,8 @@ def print_io(in_out): content += prepare_content("Out", _out) content += "-" * 56 + "\n" - logger.log_info(content) + if _out: + logger.log_info(content) def create_scaffold(project_name): From 7beedf378a7ea5c77526c42b3d4317f5bd84814b Mon Sep 17 00:00:00 2001 From: debugtalk Date: Thu, 24 Jan 2019 17:10:35 +0800 Subject: [PATCH 3/7] print testcase output --- httprunner/api.py | 5 +-- httprunner/runner.py | 10 ++--- httprunner/utils.py | 89 +++++++++++++++++++------------------------- 3 files changed, 43 insertions(+), 61 deletions(-) diff --git a/httprunner/api.py b/httprunner/api.py index 43292e00..7f693f87 100644 --- a/httprunner/api.py +++ b/httprunner/api.py @@ -145,10 +145,7 @@ class HttpRunner(object): summary["success"] &= testcase_summary["success"] testcase_summary["name"] = testcase.config.get("name") - - in_out = utils.get_testcase_io(testcase) - utils.print_io(in_out) - testcase_summary["in_out"] = in_out + testcase_summary["in_out"] = utils.get_testcase_io(testcase) report.aggregate_stat(summary["stat"]["teststeps"], testcase_summary["stat"]) report.aggregate_stat(summary["time"], testcase_summary["time"]) diff --git a/httprunner/runner.py b/httprunner/runner.py index 32fc6572..71147e57 100644 --- a/httprunner/runner.py +++ b/httprunner/runner.py @@ -309,7 +309,9 @@ class Runner(object): _meta_datas = test_runner.meta_datas self.meta_datas.append(_meta_datas) - self.session_context.update_session_variables(test_runner.extract_sessions()) + self.session_context.update_session_variables( + test_runner.extract_output(test_runner.output) + ) def run_test(self, test_dict): """ run single teststep of testcase. @@ -360,11 +362,6 @@ class Runner(object): finally: self.meta_datas = self.__get_test_data() - def extract_sessions(self): - """ - """ - return self.extract_output(self.output) - def extract_output(self, output_variables_list): """ extract output variables """ @@ -381,4 +378,5 @@ class Runner(object): output[variable] = variables_mapping[variable] + utils.print_info(output) return output diff --git a/httprunner/utils.py b/httprunner/utils.py index e9ba70f3..88eecacd 100644 --- a/httprunner/utils.py +++ b/httprunner/utils.py @@ -433,13 +433,12 @@ def extend_variables(raw_variables, override_variables): def get_testcase_io(testcase): - """ get testcase input(variables) and output. + """ get and print testcase input(variables) and output. Args: testcase (unittest.suite.TestSuite): corresponding to one YAML/JSON file, it has been set two attributes: config: parsed config block runner: initialized runner.Runner() with config - Returns: dict: input(variables) and output mapping. @@ -447,73 +446,61 @@ def get_testcase_io(testcase): test_runner = testcase.runner variables = testcase.config.get("variables", {}) output_list = testcase.config.get("output", []) + output_mapping = test_runner.extract_output(output_list) return { "in": variables, - "out": test_runner.extract_output(output_list) + "out": output_mapping } -def print_io(in_out): - """ print input(variables) and output. +def print_info(info_mapping): + """ print info in mapping. Args: - in_out (dict): input(variables) and output mapping. + info_mapping (dict): input(variables) or output mapping. Examples: - >>> in_out = { - "in": { - "var_a": "hello", - "var_b": "world" - }, - "out": { - "status_code": 500 - } + >>> info_mapping = { + "var_a": "hello", + "var_b": "world" } - >>> print_io(in_out) - ================== Variables & Output ================== - Type | Variable : Value - ------ | ---------------- : --------------------------- - Var | var_a : hello - Var | var_b : world - - Out | status_code : 500 - -------------------------------------------------------- + >>> info_mapping = { + "status_code": 500 + } + >>> print_info(info_mapping) + ==================== Output ==================== + Key : Value + ---------------- : ---------------------------- + var_a : hello + var_b : world + ------------------------------------------------ """ - content_format = "{:<6} | {:<16} : {:<}\n" - content = "\n================== Variables & Output ==================\n" - content += content_format.format("Type", "Variable", "Value") - content += content_format.format("-" * 6, "-" * 16, "-" * 27) + if not info_mapping: + return - def prepare_content(var_type, in_out): - content = "" - for variable, value in in_out.items(): - if isinstance(value, (tuple, collections.deque)): - continue - elif isinstance(value, (dict, list)): - value = json.dumps(value) + content_format = "{:<16} : {:<}\n" + content = "\n==================== Output ====================\n" + content += content_format.format("Variable", "Value") + content += content_format.format("-" * 16, "-" * 29) - if is_py2: - if isinstance(variable, unicode): - variable = variable.encode("utf-8") - if isinstance(value, unicode): - value = value.encode("utf-8") + for key, value in info_mapping.items(): + if isinstance(value, (tuple, collections.deque)): + continue + elif isinstance(value, (dict, list)): + value = json.dumps(value) - content += content_format.format(var_type, variable, value) + if is_py2: + if isinstance(key, unicode): + key = key.encode("utf-8") + if isinstance(value, unicode): + value = value.encode("utf-8") - return content + content += content_format.format(key, value) - _in = in_out["in"] - _out = in_out["out"] - - content += prepare_content("Var", _in) - content += "\n" - content += prepare_content("Out", _out) - content += "-" * 56 + "\n" - - if _out: - logger.log_info(content) + content += "-" * 48 + "\n" + logger.log_info(content) def create_scaffold(project_name): From c17875c82c15b43507de3869873681639e70c26a Mon Sep 17 00:00:00 2001 From: debugtalk Date: Fri, 25 Jan 2019 12:18:07 +0800 Subject: [PATCH 4/7] fix duplicate API definition output --- httprunner/loader.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/httprunner/loader.py b/httprunner/loader.py index 3a34865f..daec7c4b 100644 --- a/httprunner/loader.py +++ b/httprunner/loader.py @@ -613,17 +613,23 @@ def load_api_folder(api_folder_path): if isinstance(api_items, list): for api_item in api_items: key, api_dict = api_item.popitem() - api_id = api_dict.get("id") - if api_id in api_definition_mapping: - logger.log_warning("API definition duplicated: {}".format(api_id)) + api_id = api_dict.get("id") or api_dict.get("def") or api_dict.get("name") + if key != "api" or not api_id: + raise exceptions.ParamsError( + "Invalid API defined in {}".format(api_file_path)) - api_definition_mapping[api_id] = api_dict + if api_id in api_definition_mapping: + raise exceptions.ParamsError( + "Duplicated API ({}) defined in {}".format(api_id, api_file_path)) + else: + api_definition_mapping[api_id] = api_dict elif isinstance(api_items, dict): if api_file_path in api_definition_mapping: - logger.log_warning("API definition duplicated: {}".format(api_file_path)) - - api_definition_mapping[api_file_path] = api_items + raise exceptions.ParamsError( + "Duplicated API defined: {}".format(api_file_path)) + else: + api_definition_mapping[api_file_path] = api_items return api_definition_mapping From 824cfaf515b8046d0a864901afe8fb0580db2c89 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Fri, 25 Jan 2019 13:44:19 +0800 Subject: [PATCH 5/7] each teststeps in one testcase share the same session. --- httprunner/client.py | 2 ++ httprunner/runner.py | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/httprunner/client.py b/httprunner/client.py index 3de5c47f..279c775c 100644 --- a/httprunner/client.py +++ b/httprunner/client.py @@ -169,6 +169,8 @@ class HttpSession(requests.Session): :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. """ + self.init_meta_data() + # record test name self.meta_data["name"] = name diff --git a/httprunner/runner.py b/httprunner/runner.py index 71147e57..e910cb0f 100644 --- a/httprunner/runner.py +++ b/httprunner/runner.py @@ -282,11 +282,9 @@ class Runner(object): """ self.meta_datas = [] config = testcase_dict.get("config", {}) - base_url = config.get("base_url") - # each testcase should have individual session. - http_client_session = self.http_client_session.__class__(base_url) - test_runner = Runner(config, self.functions, http_client_session) + # each teststeps in one testcase (YAML/JSON) share the same session. + test_runner = Runner(config, self.functions, self.http_client_session) tests = testcase_dict.get("teststeps", []) From 88934a066a964b0ecab7c3166b1971f72fac1dd8 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Fri, 25 Jan 2019 18:03:46 +0800 Subject: [PATCH 6/7] display result from hook functions --- httprunner/runner.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/httprunner/runner.py b/httprunner/runner.py index e910cb0f..3cf23987 100644 --- a/httprunner/runner.py +++ b/httprunner/runner.py @@ -140,10 +140,14 @@ class Runner(object): # format 1 # {"var": "${func()}"} var_name, hook_content = list(action.items())[0] - logger.log_debug("assignment with hook: {} = {}".format(var_name, hook_content)) + hook_content_eval = self.session_context.eval_content(hook_content) + logger.log_debug( + "assignment with hook: {} = {} => {}".format( + var_name, hook_content, hook_content_eval + ) + ) self.session_context.update_test_variables( - var_name, - self.session_context.eval_content(hook_content) + var_name, hook_content_eval ) else: # format 2 From c282b166145a2cbe6cf8affef26de5d63005a582 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Fri, 25 Jan 2019 19:01:27 +0800 Subject: [PATCH 7/7] update Release History --- HISTORY.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index c7b87a02..c7b9d38a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,11 +2,21 @@ ## 2.0.2 (2019-01-21) +**Bugfixes** + +- each teststeps in one testcase share the same session +- fix duplicate API definition output + +**Improvements** + +- display result from hook functions in DEBUG level log - change log level of "Variables & Output" to INFO +- print Invalid testcase path or testcases +- print testcase output in INFO level log ## 2.0.1 (2019-01-18) -Bugfixes: +**Bugfixes** - override current teststep variables with former testcase output variables - make compatible with testcase name is empty