From d76b6f15db7dc636d5b4f44a7f969651c0149aa5 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Tue, 10 Mar 2020 19:20:09 +0800 Subject: [PATCH 1/9] change: remove cli --validate --- docs/CHANGELOG.md | 3 ++- docs/prepare/validate-pretty.md | 37 +-------------------------------- httprunner/cli.py | 15 ------------- 3 files changed, 3 insertions(+), 52 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 48e18adf..54a66cc9 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -8,11 +8,12 @@ **Changed** -- replace logging with [loguru](https://github.com/Delgan/loguru) - remove support for Python 2.7 +- replace logging with [loguru](https://github.com/Delgan/loguru) - replace string format with f-string - remove dependency colorama and colorlog - generate reports/logs folder in current working directory +- remove cli `--validate` ## 2.5.7 (2020-02-21) diff --git a/docs/prepare/validate-pretty.md b/docs/prepare/validate-pretty.md index d01b74b8..62ae3610 100644 --- a/docs/prepare/validate-pretty.md +++ b/docs/prepare/validate-pretty.md @@ -1,40 +1,5 @@ -HttpRunner 从 `1.3.1` 版本开始,支持对 JSON 格式测试用例的内容进行格式正确性检测和样式美化功能。 - -## JSON 格式正确性检测 - -若需对 JSON 格式用例文件的内容进行正确性检测,可使用 `--validate` 参数。 - -可指定单个 JSON 用例文件路径。 - -```bash -$ hrun --validate docs/data/demo-quickstart.json -Start to validate JSON file: docs/data/demo-quickstart.json -OK -``` - -也可指定多个 JSON 用例文件路径。 - -```bash -$ hrun --validate docs/data/demo-quickstart.json docs/data/demo-quickstart.yml docs/data/demo-quickstart-0.json -Start to validate JSON file: docs/data/demo-quickstart.json -OK -WARNING Only JSON file format can be validated, skip docs/data/demo-quickstart.yml -Start to validate JSON file: docs/data/demo-quickstart-0.json -OK -``` - -如上所示,当传入的文件后缀不是`.json`,HttpRunner 会打印 WARNING 信息,并跳过检测。 - -若 JSON 文件格式正确,则打印 OK。 - -若 JSON 文件格式存在异常,则打印详细的报错信息,精确到错误在文件中出现的行和列。 - -```bash -$ hrun --validate docs/data/demo-quickstart.json -Start to validate JSON file: docs/data/demo-quickstart.json -Expecting ',' delimiter: line 5 column 13 (char 82) -``` +HttpRunner 从 `1.3.1` 版本开始,支持对 JSON 格式测试用例的内容进行样式美化功能。 ## JSON 格式美化 diff --git a/httprunner/cli.py b/httprunner/cli.py index 2eece0bb..bdf10f64 100644 --- a/httprunner/cli.py +++ b/httprunner/cli.py @@ -52,9 +52,6 @@ def main(): parser.add_argument( '--startproject', help="Specify new project name.") - parser.add_argument( - '--validate', nargs='*', - help="Validate YAML/JSON api/testcase/testsuite format.") parser.add_argument( '--prettify', nargs='*', help="Prettify JSON testcase format.") @@ -70,18 +67,6 @@ def main(): print(f"{__version__}") sys.exit(0) - if args.validate: - for validate_path in args.validate: - try: - logger.info(f"validate test file: {validate_path}") - load_cases(validate_path, args.dot_env_path) - except exceptions.MyBaseError as ex: - logger.error(str(ex)) - continue - - logger.info("done!") - sys.exit(0) - if args.prettify: prettify_json_file(args.prettify) sys.exit(0) From 5e4d05d1273ccf62966d7c13f9685e0b9c2118ce Mon Sep 17 00:00:00 2001 From: debugtalk Date: Tue, 10 Mar 2020 19:24:42 +0800 Subject: [PATCH 2/9] remove cli --pretty --- docs/CHANGELOG.md | 1 + docs/prepare/validate-pretty.md | 39 --------------------------------- httprunner/cli.py | 13 ++--------- httprunner/utils.py | 27 ----------------------- mkdocs.yml | 1 - 5 files changed, 3 insertions(+), 78 deletions(-) delete mode 100644 docs/prepare/validate-pretty.md diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 54a66cc9..da8e764d 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -14,6 +14,7 @@ - remove dependency colorama and colorlog - generate reports/logs folder in current working directory - remove cli `--validate` +- remove cli `--pretty` ## 2.5.7 (2020-02-21) diff --git a/docs/prepare/validate-pretty.md b/docs/prepare/validate-pretty.md deleted file mode 100644 index 62ae3610..00000000 --- a/docs/prepare/validate-pretty.md +++ /dev/null @@ -1,39 +0,0 @@ - -HttpRunner 从 `1.3.1` 版本开始,支持对 JSON 格式测试用例的内容进行样式美化功能。 - -## JSON 格式美化 - -与 YAML 格式不同,JSON 格式不强制要求缩进和换行,这有点类似于 C 语言和 Python 语言的差异。 - -例如,`demo-quickstart.json`文件也可以改写为如下形式。 - -```json -[{"config": {"name": "testcase description","variables": [],"request": {"base_url": "","headers": {"User-Agent": "python-requests/2.18.4"}}}},{"test": {"name": "/api/get-token","request": {"url": "http://127.0.0.1:5000/api/get-token","headers": {"device_sn": "FwgRiO7CNA50DSU","user_agent": "iOS/10.3","os_platform": "ios","app_version": "2.8.6","Content-Type": "application/json"},"method": "POST","json": {"sign": "9c0c7e51c91ae963c833a4ccbab8d683c4a90c98"}},"validate": [{"eq": ["status_code",200]},{"eq": ["headers.Content-Type","application/json"]},{"eq": ["content.success",true]},{"eq": ["content.token","baNLX1zhFYP11Seb"]}]}},{"test": {"name": "/api/users/1000","request": {"url": "http://127.0.0.1:5000/api/users/1000","headers": {"device_sn": "FwgRiO7CNA50DSU","token": "baNLX1zhFYP11Seb","Content-Type": "application/json"},"method": "POST","json": {"name": "user1","password": "123456"}},"validate": [{"eq": ["status_code",201]},{"eq": ["headers.Content-Type","application/json"]},{"eq": ["content.success",true]},{"eq": ["content.msg","user created successfully."]}]}}] -``` - -虽然上面 JSON 格式的测试用例也能正常执行,但测试用例文件的可读性太差,不利于阅读和维护。 - -针对该需求,可使用 `--prettify` 参数对 JSON 格式用例文件进行样式美化。 - -可指定单个 JSON 用例文件路径。 - -```bash -$ hrun --prettify docs/data/demo-quickstart.json -Start to prettify JSON file: docs/data/demo-quickstart.json -success: docs/data/demo-quickstart.pretty.json -``` - -也可指定多个 JSON 用例文件路径。 - -```bash -$ hrun --prettify docs/data/demo-quickstart.json docs/data/demo-quickstart.yml docs/data/demo-quickstart-0.json -WARNING Only JSON file format can be prettified, skip: docs/data/demo-quickstart.yml -Start to prettify JSON file: docs/data/demo-quickstart.json -success: docs/data/demo-quickstart.pretty.json -Start to prettify JSON file: docs/data/demo-quickstart-0.json -success: docs/data/demo-quickstart-0.pretty.json -``` - -如上所示,当传入的文件后缀不是`.json`,HttpRunner 会打印 WARNING 信息,并跳过检测。 - -若转换成功,则打印美化后的文件路径;若 JSON 文件格式存在异常,则打印详细的报错信息,精确到错误在文件中出现的行和列。 diff --git a/httprunner/cli.py b/httprunner/cli.py index bdf10f64..852a9495 100644 --- a/httprunner/cli.py +++ b/httprunner/cli.py @@ -5,12 +5,10 @@ import sys import sentry_sdk from loguru import logger -from httprunner import __description__, __version__, exceptions +from httprunner import __description__, __version__ from httprunner.api import HttpRunner -from httprunner.loader import load_cases from httprunner.report import gen_html_report -from httprunner.utils import (create_scaffold, - prettify_json_file, init_sentry_sdk) +from httprunner.utils import create_scaffold, init_sentry_sdk init_sentry_sdk() @@ -52,9 +50,6 @@ def main(): parser.add_argument( '--startproject', help="Specify new project name.") - parser.add_argument( - '--prettify', nargs='*', - help="Prettify JSON testcase format.") args = parser.parse_args() @@ -67,10 +62,6 @@ def main(): print(f"{__version__}") sys.exit(0) - if args.prettify: - prettify_json_file(args.prettify) - sys.exit(0) - project_name = args.startproject if project_name: create_scaffold(project_name) diff --git a/httprunner/utils.py b/httprunner/utils.py index 8536e904..75feedb5 100644 --- a/httprunner/utils.py +++ b/httprunner/utils.py @@ -514,33 +514,6 @@ def gen_cartesian_product(*args): return product_list -def prettify_json_file(file_list): - """ prettify JSON testcase format - """ - for json_file in set(file_list): - if not json_file.endswith(".json"): - logger.warning(f"Only JSON file format can be prettified, skip: {json_file}") - continue - - logger.info(f"Start to prettify JSON file: {json_file}") - - dir_path = os.path.dirname(json_file) - file_name, file_suffix = os.path.splitext(os.path.basename(json_file)) - outfile = os.path.join(dir_path, f"{file_name}.pretty.json") - - with io.open(json_file, 'r', encoding='utf-8') as stream: - try: - obj = json.load(stream) - except ValueError as e: - raise SystemExit(e) - - with io.open(outfile, 'w', encoding='utf-8') as out: - json.dump(obj, out, indent=4, separators=(',', ': ')) - out.write('\n') - - print(f"success: {outfile}") - - def omit_long_data(body, omit_len=512): """ omit too long str/bytes """ diff --git a/mkdocs.yml b/mkdocs.yml index 2ef012ca..fe71cc6b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -66,7 +66,6 @@ nav: - 环境变量: prepare/dot-env.md - 测试用例分层: prepare/testcase-layer.md - 参数化数据驱动: prepare/parameters.md - - Validate & Prettify: prepare/validate-pretty.md - 信息安全: prepare/security.md - 文件上传场景: prepare/upload-case.md - 测试执行: From d906d48b7320c9d204455e9eaf4e0228ccf88406 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Tue, 10 Mar 2020 19:53:22 +0800 Subject: [PATCH 3/9] change: prepare_log_file_abs_path --- httprunner/api.py | 33 ++++++++++++++++++++++++--------- httprunner/utils.py | 20 +++----------------- httprunner/utils_test.py | 19 ++++++------------- 3 files changed, 33 insertions(+), 39 deletions(-) diff --git a/httprunner/api.py b/httprunner/api.py index 83f79659..d829a207 100644 --- a/httprunner/api.py +++ b/httprunner/api.py @@ -50,7 +50,7 @@ class HttpRunner(object): self.test_loader = unittest.TestLoader() self.save_tests = save_tests self._summary = None - self.project_mapping = None + self.test_path = None def _add_tests(self, testcases): """ initialize testcase with Runner() and add to test suite. @@ -139,7 +139,7 @@ class HttpRunner(object): log_handler = None if self.save_tests: logs_file_abs_path = utils.prepare_log_file_abs_path( - self.project_mapping, f"testcase_{index+1}.log" + self.test_path, f"testcase_{index+1}.log" ) log_handler = logger.add(logs_file_abs_path, level="DEBUG") @@ -197,7 +197,7 @@ class HttpRunner(object): if self.save_tests: logs_file_abs_path = utils.prepare_log_file_abs_path( - self.project_mapping, f"testcase_{index + 1}.log" + self.test_path, f"testcase_{index+1}.log" ) testcase_summary["log"] = logs_file_abs_path @@ -209,10 +209,13 @@ class HttpRunner(object): """ run testcase/testsuite data """ capture_message("start to run tests") - self.project_mapping = tests_mapping.get("project_mapping", {}) + self.test_path = tests_mapping.get("project_mapping", {}).get("test_path", "") if self.save_tests: - utils.dump_logs(tests_mapping, self.project_mapping, "loaded") + utils.dump_json_file( + tests_mapping, + utils.prepare_log_file_abs_path(self.test_path, "loaded.json") + ) # parse tests self.exception_stage = "parse tests" @@ -220,14 +223,20 @@ class HttpRunner(object): parse_failed_testfiles = parser.get_parse_failed_testfiles() if parse_failed_testfiles: logger.warning("parse failures occurred ...") - utils.dump_logs(parse_failed_testfiles, self.project_mapping, "parse_failed") + utils.dump_json_file( + parse_failed_testfiles, + utils.prepare_log_file_abs_path(self.test_path, "parse_failed.json") + ) if len(parsed_testcases) == 0: logger.error("failed to parse all cases, abort.") raise exceptions.ParseTestsFailure if self.save_tests: - utils.dump_logs(parsed_testcases, self.project_mapping, "parsed") + utils.dump_json_file( + parsed_testcases, + utils.prepare_log_file_abs_path(self.test_path, "parsed.json") + ) # add tests to test suite self.exception_stage = "add tests to test suite" @@ -246,10 +255,16 @@ class HttpRunner(object): report.stringify_summary(self._summary) if self.save_tests: - utils.dump_logs(self._summary, self.project_mapping, "summary") + utils.dump_json_file( + self._summary, + utils.prepare_log_file_abs_path(self.test_path, "summary.json") + ) # save variables and export data vars_out = self.get_vars_out() - utils.dump_logs(vars_out, self.project_mapping, "io") + utils.dump_json_file( + vars_out, + utils.prepare_log_file_abs_path(self.test_path, "io.json") + ) return self._summary diff --git a/httprunner/utils.py b/httprunner/utils.py index 75feedb5..9defd265 100644 --- a/httprunner/utils.py +++ b/httprunner/utils.py @@ -8,6 +8,7 @@ import json import os.path import re import uuid +from typing import Union import sentry_sdk from loguru import logger @@ -533,7 +534,7 @@ def omit_long_data(body, omit_len=512): return omitted_body + appendix_str -def dump_json_file(json_data, json_file_abs_path): +def dump_json_file(json_data: Union[dict, list], json_file_abs_path: str) -> None: """ dump json data to file """ class PythonObjectEncoder(json.JSONEncoder): @@ -566,11 +567,10 @@ def dump_json_file(json_data, json_file_abs_path): logger.error(msg) -def prepare_log_file_abs_path(project_mapping, file_name): +def prepare_log_file_abs_path(test_path: str, file_name: str) -> str: """ prepare dump json file absolute path. """ current_working_dir = os.getcwd() - test_path = project_mapping.get("test_path") if not test_path: # running passed in testcase/testsuite data structure @@ -592,17 +592,3 @@ def prepare_log_file_abs_path(project_mapping, file_name): dumped_json_file_abs_path = os.path.join(file_foder_path, dump_file_name) return dumped_json_file_abs_path - - -def dump_logs(json_data, project_mapping, tag_name): - """ dump tests data to json file. - the dumped file is located in PWD/logs folder. - - Args: - json_data (list/dict): json data to dump - project_mapping (dict): project info - tag_name (str): tag name, loaded/parsed/summary - - """ - json_file_abs_path = prepare_log_file_abs_path(project_mapping, f"{tag_name}.json") - dump_json_file(json_data, json_file_abs_path) diff --git a/httprunner/utils_test.py b/httprunner/utils_test.py index a7130fd4..e41761d7 100644 --- a/httprunner/utils_test.py +++ b/httprunner/utils_test.py @@ -278,30 +278,23 @@ class TestUtils(unittest.TestCase): def test_prepare_dump_json_file_path_for_folder(self): # hrun tests/httpbin/a.b.c/ --save-tests - project_mapping = { - "test_path": os.path.join("tests", "httpbin", "a.b.c") - } + test_path = os.path.join("tests", "httpbin", "a.b.c") self.assertEqual( - utils.prepare_log_file_abs_path(project_mapping, "loaded"), + utils.prepare_log_file_abs_path(test_path, "loaded.json"), os.path.join(os.getcwd(), "logs", "tests/httpbin/a.b.c/all.loaded.json") ) def test_prepare_dump_json_file_path_for_file(self): # hrun tests/httpbin/a.b.c/rpc.yml --save-tests - project_mapping = { - "test_path": os.path.join("tests", "httpbin", "a.b.c", "rpc.yml") - } + test_path = os.path.join("tests", "httpbin", "a.b.c", "rpc.yml") self.assertEqual( - utils.prepare_log_file_abs_path(project_mapping, "loaded"), + utils.prepare_log_file_abs_path(test_path, "loaded.json"), os.path.join(os.getcwd(), "logs", "tests/httpbin/a.b.c/rpc.loaded.json") ) def test_prepare_dump_json_file_path_for_passed_testcase(self): - project_working_directory = os.path.join(os.getcwd(), "tests") - project_mapping = { - "PWD": project_working_directory - } + test_path = "" self.assertEqual( - utils.prepare_log_file_abs_path(project_mapping, "loaded"), + utils.prepare_log_file_abs_path(test_path, "loaded.json"), os.path.join(os.getcwd(), "logs", "tests_mapping.loaded.json") ) From 21542b1f99aa7eda5a52c6d1897a5b4d1123808c Mon Sep 17 00:00:00 2001 From: debugtalk Date: Tue, 10 Mar 2020 19:20:09 +0800 Subject: [PATCH 4/9] change: remove cli --validate --- docs/CHANGELOG.md | 3 ++- docs/prepare/validate-pretty.md | 37 +-------------------------------- httprunner/cli.py | 15 ------------- 3 files changed, 3 insertions(+), 52 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 48e18adf..54a66cc9 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -8,11 +8,12 @@ **Changed** -- replace logging with [loguru](https://github.com/Delgan/loguru) - remove support for Python 2.7 +- replace logging with [loguru](https://github.com/Delgan/loguru) - replace string format with f-string - remove dependency colorama and colorlog - generate reports/logs folder in current working directory +- remove cli `--validate` ## 2.5.7 (2020-02-21) diff --git a/docs/prepare/validate-pretty.md b/docs/prepare/validate-pretty.md index d01b74b8..62ae3610 100644 --- a/docs/prepare/validate-pretty.md +++ b/docs/prepare/validate-pretty.md @@ -1,40 +1,5 @@ -HttpRunner 从 `1.3.1` 版本开始,支持对 JSON 格式测试用例的内容进行格式正确性检测和样式美化功能。 - -## JSON 格式正确性检测 - -若需对 JSON 格式用例文件的内容进行正确性检测,可使用 `--validate` 参数。 - -可指定单个 JSON 用例文件路径。 - -```bash -$ hrun --validate docs/data/demo-quickstart.json -Start to validate JSON file: docs/data/demo-quickstart.json -OK -``` - -也可指定多个 JSON 用例文件路径。 - -```bash -$ hrun --validate docs/data/demo-quickstart.json docs/data/demo-quickstart.yml docs/data/demo-quickstart-0.json -Start to validate JSON file: docs/data/demo-quickstart.json -OK -WARNING Only JSON file format can be validated, skip docs/data/demo-quickstart.yml -Start to validate JSON file: docs/data/demo-quickstart-0.json -OK -``` - -如上所示,当传入的文件后缀不是`.json`,HttpRunner 会打印 WARNING 信息,并跳过检测。 - -若 JSON 文件格式正确,则打印 OK。 - -若 JSON 文件格式存在异常,则打印详细的报错信息,精确到错误在文件中出现的行和列。 - -```bash -$ hrun --validate docs/data/demo-quickstart.json -Start to validate JSON file: docs/data/demo-quickstart.json -Expecting ',' delimiter: line 5 column 13 (char 82) -``` +HttpRunner 从 `1.3.1` 版本开始,支持对 JSON 格式测试用例的内容进行样式美化功能。 ## JSON 格式美化 diff --git a/httprunner/cli.py b/httprunner/cli.py index 2eece0bb..bdf10f64 100644 --- a/httprunner/cli.py +++ b/httprunner/cli.py @@ -52,9 +52,6 @@ def main(): parser.add_argument( '--startproject', help="Specify new project name.") - parser.add_argument( - '--validate', nargs='*', - help="Validate YAML/JSON api/testcase/testsuite format.") parser.add_argument( '--prettify', nargs='*', help="Prettify JSON testcase format.") @@ -70,18 +67,6 @@ def main(): print(f"{__version__}") sys.exit(0) - if args.validate: - for validate_path in args.validate: - try: - logger.info(f"validate test file: {validate_path}") - load_cases(validate_path, args.dot_env_path) - except exceptions.MyBaseError as ex: - logger.error(str(ex)) - continue - - logger.info("done!") - sys.exit(0) - if args.prettify: prettify_json_file(args.prettify) sys.exit(0) From a8879fbc97ebed86ece8e6a3f966ff7ed79162e1 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Tue, 10 Mar 2020 19:24:42 +0800 Subject: [PATCH 5/9] remove cli --pretty --- docs/CHANGELOG.md | 1 + docs/prepare/validate-pretty.md | 39 --------------------------------- httprunner/cli.py | 13 ++--------- httprunner/utils.py | 27 ----------------------- mkdocs.yml | 1 - 5 files changed, 3 insertions(+), 78 deletions(-) delete mode 100644 docs/prepare/validate-pretty.md diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 54a66cc9..da8e764d 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -14,6 +14,7 @@ - remove dependency colorama and colorlog - generate reports/logs folder in current working directory - remove cli `--validate` +- remove cli `--pretty` ## 2.5.7 (2020-02-21) diff --git a/docs/prepare/validate-pretty.md b/docs/prepare/validate-pretty.md deleted file mode 100644 index 62ae3610..00000000 --- a/docs/prepare/validate-pretty.md +++ /dev/null @@ -1,39 +0,0 @@ - -HttpRunner 从 `1.3.1` 版本开始,支持对 JSON 格式测试用例的内容进行样式美化功能。 - -## JSON 格式美化 - -与 YAML 格式不同,JSON 格式不强制要求缩进和换行,这有点类似于 C 语言和 Python 语言的差异。 - -例如,`demo-quickstart.json`文件也可以改写为如下形式。 - -```json -[{"config": {"name": "testcase description","variables": [],"request": {"base_url": "","headers": {"User-Agent": "python-requests/2.18.4"}}}},{"test": {"name": "/api/get-token","request": {"url": "http://127.0.0.1:5000/api/get-token","headers": {"device_sn": "FwgRiO7CNA50DSU","user_agent": "iOS/10.3","os_platform": "ios","app_version": "2.8.6","Content-Type": "application/json"},"method": "POST","json": {"sign": "9c0c7e51c91ae963c833a4ccbab8d683c4a90c98"}},"validate": [{"eq": ["status_code",200]},{"eq": ["headers.Content-Type","application/json"]},{"eq": ["content.success",true]},{"eq": ["content.token","baNLX1zhFYP11Seb"]}]}},{"test": {"name": "/api/users/1000","request": {"url": "http://127.0.0.1:5000/api/users/1000","headers": {"device_sn": "FwgRiO7CNA50DSU","token": "baNLX1zhFYP11Seb","Content-Type": "application/json"},"method": "POST","json": {"name": "user1","password": "123456"}},"validate": [{"eq": ["status_code",201]},{"eq": ["headers.Content-Type","application/json"]},{"eq": ["content.success",true]},{"eq": ["content.msg","user created successfully."]}]}}] -``` - -虽然上面 JSON 格式的测试用例也能正常执行,但测试用例文件的可读性太差,不利于阅读和维护。 - -针对该需求,可使用 `--prettify` 参数对 JSON 格式用例文件进行样式美化。 - -可指定单个 JSON 用例文件路径。 - -```bash -$ hrun --prettify docs/data/demo-quickstart.json -Start to prettify JSON file: docs/data/demo-quickstart.json -success: docs/data/demo-quickstart.pretty.json -``` - -也可指定多个 JSON 用例文件路径。 - -```bash -$ hrun --prettify docs/data/demo-quickstart.json docs/data/demo-quickstart.yml docs/data/demo-quickstart-0.json -WARNING Only JSON file format can be prettified, skip: docs/data/demo-quickstart.yml -Start to prettify JSON file: docs/data/demo-quickstart.json -success: docs/data/demo-quickstart.pretty.json -Start to prettify JSON file: docs/data/demo-quickstart-0.json -success: docs/data/demo-quickstart-0.pretty.json -``` - -如上所示,当传入的文件后缀不是`.json`,HttpRunner 会打印 WARNING 信息,并跳过检测。 - -若转换成功,则打印美化后的文件路径;若 JSON 文件格式存在异常,则打印详细的报错信息,精确到错误在文件中出现的行和列。 diff --git a/httprunner/cli.py b/httprunner/cli.py index bdf10f64..852a9495 100644 --- a/httprunner/cli.py +++ b/httprunner/cli.py @@ -5,12 +5,10 @@ import sys import sentry_sdk from loguru import logger -from httprunner import __description__, __version__, exceptions +from httprunner import __description__, __version__ from httprunner.api import HttpRunner -from httprunner.loader import load_cases from httprunner.report import gen_html_report -from httprunner.utils import (create_scaffold, - prettify_json_file, init_sentry_sdk) +from httprunner.utils import create_scaffold, init_sentry_sdk init_sentry_sdk() @@ -52,9 +50,6 @@ def main(): parser.add_argument( '--startproject', help="Specify new project name.") - parser.add_argument( - '--prettify', nargs='*', - help="Prettify JSON testcase format.") args = parser.parse_args() @@ -67,10 +62,6 @@ def main(): print(f"{__version__}") sys.exit(0) - if args.prettify: - prettify_json_file(args.prettify) - sys.exit(0) - project_name = args.startproject if project_name: create_scaffold(project_name) diff --git a/httprunner/utils.py b/httprunner/utils.py index 8536e904..75feedb5 100644 --- a/httprunner/utils.py +++ b/httprunner/utils.py @@ -514,33 +514,6 @@ def gen_cartesian_product(*args): return product_list -def prettify_json_file(file_list): - """ prettify JSON testcase format - """ - for json_file in set(file_list): - if not json_file.endswith(".json"): - logger.warning(f"Only JSON file format can be prettified, skip: {json_file}") - continue - - logger.info(f"Start to prettify JSON file: {json_file}") - - dir_path = os.path.dirname(json_file) - file_name, file_suffix = os.path.splitext(os.path.basename(json_file)) - outfile = os.path.join(dir_path, f"{file_name}.pretty.json") - - with io.open(json_file, 'r', encoding='utf-8') as stream: - try: - obj = json.load(stream) - except ValueError as e: - raise SystemExit(e) - - with io.open(outfile, 'w', encoding='utf-8') as out: - json.dump(obj, out, indent=4, separators=(',', ': ')) - out.write('\n') - - print(f"success: {outfile}") - - def omit_long_data(body, omit_len=512): """ omit too long str/bytes """ diff --git a/mkdocs.yml b/mkdocs.yml index 2ef012ca..fe71cc6b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -66,7 +66,6 @@ nav: - 环境变量: prepare/dot-env.md - 测试用例分层: prepare/testcase-layer.md - 参数化数据驱动: prepare/parameters.md - - Validate & Prettify: prepare/validate-pretty.md - 信息安全: prepare/security.md - 文件上传场景: prepare/upload-case.md - 测试执行: From b1fcf46d66e31aff9820abf667840f029fcbc44b Mon Sep 17 00:00:00 2001 From: debugtalk Date: Tue, 10 Mar 2020 19:53:22 +0800 Subject: [PATCH 6/9] change: prepare_log_file_abs_path --- httprunner/api.py | 33 ++++++++++++++++++++++++--------- httprunner/utils.py | 20 +++----------------- httprunner/utils_test.py | 19 ++++++------------- 3 files changed, 33 insertions(+), 39 deletions(-) diff --git a/httprunner/api.py b/httprunner/api.py index 83f79659..d829a207 100644 --- a/httprunner/api.py +++ b/httprunner/api.py @@ -50,7 +50,7 @@ class HttpRunner(object): self.test_loader = unittest.TestLoader() self.save_tests = save_tests self._summary = None - self.project_mapping = None + self.test_path = None def _add_tests(self, testcases): """ initialize testcase with Runner() and add to test suite. @@ -139,7 +139,7 @@ class HttpRunner(object): log_handler = None if self.save_tests: logs_file_abs_path = utils.prepare_log_file_abs_path( - self.project_mapping, f"testcase_{index+1}.log" + self.test_path, f"testcase_{index+1}.log" ) log_handler = logger.add(logs_file_abs_path, level="DEBUG") @@ -197,7 +197,7 @@ class HttpRunner(object): if self.save_tests: logs_file_abs_path = utils.prepare_log_file_abs_path( - self.project_mapping, f"testcase_{index + 1}.log" + self.test_path, f"testcase_{index+1}.log" ) testcase_summary["log"] = logs_file_abs_path @@ -209,10 +209,13 @@ class HttpRunner(object): """ run testcase/testsuite data """ capture_message("start to run tests") - self.project_mapping = tests_mapping.get("project_mapping", {}) + self.test_path = tests_mapping.get("project_mapping", {}).get("test_path", "") if self.save_tests: - utils.dump_logs(tests_mapping, self.project_mapping, "loaded") + utils.dump_json_file( + tests_mapping, + utils.prepare_log_file_abs_path(self.test_path, "loaded.json") + ) # parse tests self.exception_stage = "parse tests" @@ -220,14 +223,20 @@ class HttpRunner(object): parse_failed_testfiles = parser.get_parse_failed_testfiles() if parse_failed_testfiles: logger.warning("parse failures occurred ...") - utils.dump_logs(parse_failed_testfiles, self.project_mapping, "parse_failed") + utils.dump_json_file( + parse_failed_testfiles, + utils.prepare_log_file_abs_path(self.test_path, "parse_failed.json") + ) if len(parsed_testcases) == 0: logger.error("failed to parse all cases, abort.") raise exceptions.ParseTestsFailure if self.save_tests: - utils.dump_logs(parsed_testcases, self.project_mapping, "parsed") + utils.dump_json_file( + parsed_testcases, + utils.prepare_log_file_abs_path(self.test_path, "parsed.json") + ) # add tests to test suite self.exception_stage = "add tests to test suite" @@ -246,10 +255,16 @@ class HttpRunner(object): report.stringify_summary(self._summary) if self.save_tests: - utils.dump_logs(self._summary, self.project_mapping, "summary") + utils.dump_json_file( + self._summary, + utils.prepare_log_file_abs_path(self.test_path, "summary.json") + ) # save variables and export data vars_out = self.get_vars_out() - utils.dump_logs(vars_out, self.project_mapping, "io") + utils.dump_json_file( + vars_out, + utils.prepare_log_file_abs_path(self.test_path, "io.json") + ) return self._summary diff --git a/httprunner/utils.py b/httprunner/utils.py index 75feedb5..9defd265 100644 --- a/httprunner/utils.py +++ b/httprunner/utils.py @@ -8,6 +8,7 @@ import json import os.path import re import uuid +from typing import Union import sentry_sdk from loguru import logger @@ -533,7 +534,7 @@ def omit_long_data(body, omit_len=512): return omitted_body + appendix_str -def dump_json_file(json_data, json_file_abs_path): +def dump_json_file(json_data: Union[dict, list], json_file_abs_path: str) -> None: """ dump json data to file """ class PythonObjectEncoder(json.JSONEncoder): @@ -566,11 +567,10 @@ def dump_json_file(json_data, json_file_abs_path): logger.error(msg) -def prepare_log_file_abs_path(project_mapping, file_name): +def prepare_log_file_abs_path(test_path: str, file_name: str) -> str: """ prepare dump json file absolute path. """ current_working_dir = os.getcwd() - test_path = project_mapping.get("test_path") if not test_path: # running passed in testcase/testsuite data structure @@ -592,17 +592,3 @@ def prepare_log_file_abs_path(project_mapping, file_name): dumped_json_file_abs_path = os.path.join(file_foder_path, dump_file_name) return dumped_json_file_abs_path - - -def dump_logs(json_data, project_mapping, tag_name): - """ dump tests data to json file. - the dumped file is located in PWD/logs folder. - - Args: - json_data (list/dict): json data to dump - project_mapping (dict): project info - tag_name (str): tag name, loaded/parsed/summary - - """ - json_file_abs_path = prepare_log_file_abs_path(project_mapping, f"{tag_name}.json") - dump_json_file(json_data, json_file_abs_path) diff --git a/httprunner/utils_test.py b/httprunner/utils_test.py index a7130fd4..e41761d7 100644 --- a/httprunner/utils_test.py +++ b/httprunner/utils_test.py @@ -278,30 +278,23 @@ class TestUtils(unittest.TestCase): def test_prepare_dump_json_file_path_for_folder(self): # hrun tests/httpbin/a.b.c/ --save-tests - project_mapping = { - "test_path": os.path.join("tests", "httpbin", "a.b.c") - } + test_path = os.path.join("tests", "httpbin", "a.b.c") self.assertEqual( - utils.prepare_log_file_abs_path(project_mapping, "loaded"), + utils.prepare_log_file_abs_path(test_path, "loaded.json"), os.path.join(os.getcwd(), "logs", "tests/httpbin/a.b.c/all.loaded.json") ) def test_prepare_dump_json_file_path_for_file(self): # hrun tests/httpbin/a.b.c/rpc.yml --save-tests - project_mapping = { - "test_path": os.path.join("tests", "httpbin", "a.b.c", "rpc.yml") - } + test_path = os.path.join("tests", "httpbin", "a.b.c", "rpc.yml") self.assertEqual( - utils.prepare_log_file_abs_path(project_mapping, "loaded"), + utils.prepare_log_file_abs_path(test_path, "loaded.json"), os.path.join(os.getcwd(), "logs", "tests/httpbin/a.b.c/rpc.loaded.json") ) def test_prepare_dump_json_file_path_for_passed_testcase(self): - project_working_directory = os.path.join(os.getcwd(), "tests") - project_mapping = { - "PWD": project_working_directory - } + test_path = "" self.assertEqual( - utils.prepare_log_file_abs_path(project_mapping, "loaded"), + utils.prepare_log_file_abs_path(test_path, "loaded.json"), os.path.join(os.getcwd(), "logs", "tests_mapping.loaded.json") ) From 498bcabae08e53661f8309ba6a73c38cbfc7ef48 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Fri, 13 Mar 2020 19:36:47 +0800 Subject: [PATCH 7/9] feat: add default header HRUN-Request-ID for each testcase --- httprunner/runner.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/httprunner/runner.py b/httprunner/runner.py index f6ea0eb7..9e90303e 100644 --- a/httprunner/runner.py +++ b/httprunner/runner.py @@ -1,5 +1,4 @@ -# encoding: utf-8 - +import uuid from enum import Enum from unittest.case import SkipTest @@ -73,6 +72,10 @@ class Runner(object): self.export = config.get("export") or config.get("output", []) config_variables = config.get("variables", {}) + self.hrun_request_id = str(uuid.uuid4()) + if "HRUN-Request-ID" not in config_variables: + config_variables["HRUN-Request-ID"] = self.hrun_request_id + # testcase setup hooks testcase_setup_hooks = config.get("setup_hooks", []) # testcase teardown hooks @@ -222,6 +225,11 @@ class Runner(object): base_url = self.session_context.eval_content(test_dict.get("base_url", "")) parsed_url = utils.build_url(base_url, url) + request_headers = parsed_test_request.setdefault("headers", {}) + if "HRUN-Request-ID" not in request_headers: + parsed_test_request["headers"]["HRUN-Request-ID"] = \ + self.session_context.session_variables_mapping["HRUN-Request-ID"] + try: method = parsed_test_request.pop('method') parsed_test_request.setdefault("verify", self.verify) From 82d28344f5980307dc261694adab5119088e8c3b Mon Sep 17 00:00:00 2001 From: debugtalk Date: Fri, 13 Mar 2020 19:47:54 +0800 Subject: [PATCH 8/9] feat: save testcase HRUN-Request-ID in summary.json --- httprunner/api.py | 1 + httprunner/runner.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/httprunner/api.py b/httprunner/api.py index d829a207..67b4b942 100644 --- a/httprunner/api.py +++ b/httprunner/api.py @@ -201,6 +201,7 @@ class HttpRunner(object): ) testcase_summary["log"] = logs_file_abs_path + testcase_summary["HRUN-Request-ID"] = testcase.runner.hrun_request_id summary["details"].append(testcase_summary) return summary diff --git a/httprunner/runner.py b/httprunner/runner.py index 9e90303e..71e2f723 100644 --- a/httprunner/runner.py +++ b/httprunner/runner.py @@ -75,6 +75,8 @@ class Runner(object): self.hrun_request_id = str(uuid.uuid4()) if "HRUN-Request-ID" not in config_variables: config_variables["HRUN-Request-ID"] = self.hrun_request_id + else: + self.hrun_request_id = config_variables["HRUN-Request-ID"] # testcase setup hooks testcase_setup_hooks = config.get("setup_hooks", []) From 0921ad38e4c6d2d621565c91a0f85305029d19cc Mon Sep 17 00:00:00 2001 From: debugtalk Date: Fri, 13 Mar 2020 20:00:21 +0800 Subject: [PATCH 9/9] update changelog --- docs/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index da8e764d..b74423a3 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -5,6 +5,7 @@ **Added** - feat: dump log for each testcase +- feat: add default header `HRUN-Request-ID` for each testcase #721 **Changed**