From 1aacc28dd150c258504e6ca41fbbe218ac71ba2d Mon Sep 17 00:00:00 2001 From: debugtalk Date: Tue, 23 Jun 2020 16:27:08 +0800 Subject: [PATCH 01/13] fix: missing setup/teardown hooks for referenced testcase --- docs/CHANGELOG.md | 8 +++++++- .../request_with_functions_test.py | 2 +- .../request_with_testcase_reference.yml | 4 ++++ .../request_with_testcase_reference_test.py | 4 +++- httprunner/__init__.py | 2 +- httprunner/runner.py | 18 +++++++++++++----- httprunner/testcase.py | 16 ++++++++++++++++ pyproject.toml | 2 +- 8 files changed, 46 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 2fb4f91d..2870880e 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,5 +1,11 @@ # Release History +## 3.1.2 (2020-06-23) + +**Fixed** + +- fix: missing setup/teardown hooks for referenced testcase + ## 3.1.1 (2020-06-23) **Added** @@ -8,7 +14,7 @@ **Fixed** -- fix #942: type_match None +- fix: ValueError when type_match None - fix: override referenced testcase export in teststep - fix: avoid duplicate import - fix: override locust weight diff --git a/examples/postman_echo/request_methods/request_with_functions_test.py b/examples/postman_echo/request_methods/request_with_functions_test.py index 99d3731f..996eed64 100644 --- a/examples/postman_echo/request_methods/request_with_functions_test.py +++ b/examples/postman_echo/request_methods/request_with_functions_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: request_methods/request_with_functions.yml from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase diff --git a/examples/postman_echo/request_methods/request_with_testcase_reference.yml b/examples/postman_echo/request_methods/request_with_testcase_reference.yml index 7cd6630e..abb51f3e 100644 --- a/examples/postman_echo/request_methods/request_with_testcase_reference.yml +++ b/examples/postman_echo/request_methods/request_with_testcase_reference.yml @@ -13,7 +13,11 @@ teststeps: variables: foo1: testcase_ref_bar1 expect_foo1: testcase_ref_bar1 + setup_hooks: + - ${sleep(0.1)} testcase: request_methods/request_with_functions.yml + teardown_hooks: + - ${sleep(0.2)} export: - foo3 - diff --git a/examples/postman_echo/request_methods/request_with_testcase_reference_test.py b/examples/postman_echo/request_methods/request_with_testcase_reference_test.py index 7154992b..2d57795e 100644 --- a/examples/postman_echo/request_methods/request_with_testcase_reference_test.py +++ b/examples/postman_echo/request_methods/request_with_testcase_reference_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: request_methods/request_with_testcase_reference.yml import sys @@ -33,7 +33,9 @@ class TestCaseRequestWithTestcaseReference(HttpRunner): .with_variables( **{"foo1": "testcase_ref_bar1", "expect_foo1": "testcase_ref_bar1"} ) + .setup_hook("${sleep(0.1)}") .call(RequestWithFunctions) + .teardown_hook("${sleep(0.2)}") .export(*["foo3"]) ), Step( diff --git a/httprunner/__init__.py b/httprunner/__init__.py index 55eeae4b..6118a14a 100644 --- a/httprunner/__init__.py +++ b/httprunner/__init__.py @@ -1,4 +1,4 @@ -__version__ = "3.1.1" +__version__ = "3.1.2" __description__ = "One-stop solution for HTTP(S) testing." # import firstly for monkey patch if needed diff --git a/httprunner/runner.py b/httprunner/runner.py index ab9b4efa..f916a2d7 100644 --- a/httprunner/runner.py +++ b/httprunner/runner.py @@ -89,7 +89,7 @@ class HttpRunner(object): return self def __call_hooks( - self, hooks: Hooks, step_variables: VariablesMapping, hook_type: Text, + self, hooks: Hooks, step_variables: VariablesMapping, hook_msg: Text, ) -> NoReturn: """ call hook actions. @@ -106,10 +106,10 @@ class HttpRunner(object): request: parsed request dict response: ResponseObject for current response - hook_type: setup/teardown + hook_msg: setup/teardown request/testcase """ - logger.debug(f"call {hook_type} hook actions.") + logger.info(f"call hook actions: {hook_msg}") if not isinstance(hooks, List): logger.error(f"Invalid hooks format: {hooks}") @@ -153,7 +153,7 @@ class HttpRunner(object): # setup hooks if step.setup_hooks: - self.__call_hooks(step.setup_hooks, step.variables, "setup") + self.__call_hooks(step.setup_hooks, step.variables, "setup request") # prepare arguments method = parsed_request_dict.pop("method") @@ -169,7 +169,7 @@ class HttpRunner(object): # teardown hooks if step.teardown_hooks: - self.__call_hooks(step.teardown_hooks, step.variables, "teardown") + self.__call_hooks(step.teardown_hooks, step.variables, "teardown request") def log_req_resp_details(): err_msg = "\n{} DETAILED REQUEST & RESPONSE {}\n".format("*" * 32, "*" * 32) @@ -236,6 +236,10 @@ class HttpRunner(object): step_variables = step.variables step_export = step.export + # setup hooks + if step.setup_hooks: + self.__call_hooks(step.setup_hooks, step_variables, "setup testcase") + if hasattr(step.testcase, "config") and hasattr(step.testcase, "teststeps"): testcase_cls = step.testcase case_result = ( @@ -269,6 +273,10 @@ class HttpRunner(object): f"Invalid teststep referenced testcase: {step.dict()}" ) + # teardown hooks + if step.teardown_hooks: + self.__call_hooks(step.teardown_hooks, step.variables, "teardown testcase") + step_data.data = case_result.get_step_datas() # list of step data step_data.export_vars = case_result.get_export_variables() step_data.success = case_result.success diff --git a/httprunner/testcase.py b/httprunner/testcase.py index f6bb0e84..f8044d95 100644 --- a/httprunner/testcase.py +++ b/httprunner/testcase.py @@ -350,6 +350,14 @@ class StepRefCase(object): def __init__(self, step_context: TStep): self.__step_context = step_context + def teardown_hook(self, hook: Text, assign_var_name: Text = None) -> "StepRefCase": + if assign_var_name: + self.__step_context.teardown_hooks.append({assign_var_name: hook}) + else: + self.__step_context.teardown_hooks.append(hook) + + return self + def export(self, *var_name: Text) -> "StepRefCase": self.__step_context.export.extend(var_name) return self @@ -366,6 +374,14 @@ class RunTestCase(object): self.__step_context.variables.update(variables) return self + def setup_hook(self, hook: Text, assign_var_name: Text = None) -> "RunTestCase": + if assign_var_name: + self.__step_context.setup_hooks.append({assign_var_name: hook}) + else: + self.__step_context.setup_hooks.append(hook) + + return self + def call(self, testcase: Callable) -> StepRefCase: self.__step_context.testcase = testcase return StepRefCase(self.__step_context) diff --git a/pyproject.toml b/pyproject.toml index 5a1e5314..e300377b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "httprunner" -version = "3.1.1" +version = "3.1.2" description = "One-stop solution for HTTP(S) testing." license = "Apache-2.0" readme = "README.md" From 48e308f8d9f8b05e5587201780861c0fec9028fa Mon Sep 17 00:00:00 2001 From: debugtalk Date: Sun, 28 Jun 2020 20:45:07 +0800 Subject: [PATCH 02/13] fix: compatibility for `black` on Android termux system that does not support multiprocessing --- docs/CHANGELOG.md | 3 ++- httprunner/make.py | 10 ++++++++-- httprunner/utils.py | 13 ++++++++++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 2870880e..669ae263 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,10 +1,11 @@ # Release History -## 3.1.2 (2020-06-23) +## 3.1.2 (2020-06-28) **Fixed** - fix: missing setup/teardown hooks for referenced testcase +- fix: compatibility for `black` on Android termux that does not support multiprocessing well ## 3.1.1 (2020-06-23) diff --git a/httprunner/make.py b/httprunner/make.py index 4cb86e87..c0bf71c2 100644 --- a/httprunner/make.py +++ b/httprunner/make.py @@ -24,7 +24,7 @@ from httprunner.loader import ( convert_relative_project_root_dir, ) from httprunner.response import uniform_validator -from httprunner.utils import override_config_variables +from httprunner.utils import override_config_variables, is_support_multiprocessing """ cache converted pytest files, avoid duplicate making """ @@ -160,7 +160,13 @@ def convert_testcase_path(testcase_abs_path: Text) -> Tuple[Text, Text]: def format_pytest_with_black(*python_paths: Text) -> NoReturn: logger.info("format pytest cases with black ...") try: - subprocess.run(["black", *python_paths]) + if is_support_multiprocessing() or len(python_paths) <= 1: + subprocess.run(["black", *python_paths]) + else: + logger.warning( + f"this system does not support multiprocessing well, format files one by one ..." + ) + [subprocess.run(["black", path]) for path in python_paths] except subprocess.CalledProcessError as ex: capture_exception(ex) logger.error(ex) diff --git a/httprunner/utils.py b/httprunner/utils.py index d832f881..c0e27ed9 100644 --- a/httprunner/utils.py +++ b/httprunner/utils.py @@ -4,13 +4,15 @@ import json import os.path import platform import uuid +from multiprocessing import Queue from typing import Dict, List, Any import sentry_sdk +from loguru import logger + from httprunner import __version__ from httprunner import exceptions from httprunner.models import VariablesMapping -from loguru import logger def init_sentry_sdk(): @@ -209,3 +211,12 @@ def override_config_variables( variables = copy.deepcopy(config_variables) variables.update(step_new_variables) return variables + + +def is_support_multiprocessing() -> bool: + try: + Queue() + return True + except (ImportError, OSError): + # system that does not support semaphores(dependency of multiprocessing), like Android termux + return False From 5238cb369c71ebbfaf851ed23635cc97e50cc860 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 29 Jun 2020 11:06:19 +0800 Subject: [PATCH 03/13] fix: NameError, name 'locust_main' is not defined --- docs/CHANGELOG.md | 6 +++++- httprunner/ext/locust/__init__.py | 19 ++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 669ae263..ec3fce4a 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,12 +1,16 @@ # Release History -## 3.1.2 (2020-06-28) +## 3.1.2 (2020-06-29) **Fixed** - fix: missing setup/teardown hooks for referenced testcase - fix: compatibility for `black` on Android termux that does not support multiprocessing well +**Changed** + +- change: import locust at beginning to monkey patch all modules + ## 3.1.1 (2020-06-23) **Added** diff --git a/httprunner/ext/locust/__init__.py b/httprunner/ext/locust/__init__.py index fe528e68..38214567 100644 --- a/httprunner/ext/locust/__init__.py +++ b/httprunner/ext/locust/__init__.py @@ -1,16 +1,12 @@ -import importlib.util -import inspect -import os import sys -from typing import List -if sys.argv[0].endswith("locusts"): +if "locust" in sys.argv[0]: try: - # monkey patch ssl at beginning to avoid RecursionError when running locust. - from gevent import monkey - - monkey.patch_ssl() + # monkey patch all at beginning to avoid RecursionError when running locust. + # `from gevent import monkey; monkey.patch_all()` will be triggered when importing locust from locust import main as locust_main + + print("NOTICE: gevent monkey patches have been applied !!!") except ImportError: msg = """ Locust is not installed, install first and try again. @@ -20,9 +16,14 @@ $ pip install locust print(msg) sys.exit(1) +import importlib.util +import inspect +import os +from typing import List from loguru import logger + """ converted pytest files from YAML/JSON testcases """ pytest_files: List = [] From be6ec10271bcdd3c021704c633863d2036085f53 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 29 Jun 2020 14:29:56 +0800 Subject: [PATCH 04/13] change: replace io.open with open --- httprunner/ext/har2case/utils.py | 7 +++---- httprunner/loader.py | 9 ++++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/httprunner/ext/har2case/utils.py b/httprunner/ext/har2case/utils.py index ed200995..110f8b40 100644 --- a/httprunner/ext/har2case/utils.py +++ b/httprunner/ext/har2case/utils.py @@ -1,4 +1,3 @@ -import io import json import sys from json.decoder import JSONDecodeError @@ -28,7 +27,7 @@ def load_har_log_entries(file_path): ] """ - with io.open(file_path, "r+", encoding="utf-8-sig") as f: + with open(file_path, encoding="utf-8") as f: try: content_json = json.loads(f.read()) return content_json["log"]["entries"] @@ -108,7 +107,7 @@ def dump_yaml(testcase, yaml_file): """ logger.info("dump testcase to YAML format.") - with io.open(yaml_file, "w", encoding="utf-8") as outfile: + with open(yaml_file, "w", encoding="utf-8") as outfile: yaml.dump( testcase, outfile, allow_unicode=True, default_flow_style=False, indent=4 ) @@ -121,7 +120,7 @@ def dump_json(testcase, json_file): """ logger.info("dump testcase to JSON format.") - with io.open(json_file, "w", encoding="utf-8") as outfile: + with open(json_file, "w", encoding="utf-8") as outfile: my_json_str = json.dumps(testcase, ensure_ascii=False, indent=4) if isinstance(my_json_str, bytes): my_json_str = my_json_str.decode("utf-8") diff --git a/httprunner/loader.py b/httprunner/loader.py index 429b4d07..b389c716 100644 --- a/httprunner/loader.py +++ b/httprunner/loader.py @@ -1,6 +1,5 @@ import csv import importlib -import io import json import os import sys @@ -29,7 +28,7 @@ project_meta: Union[ProjectMeta, None] = None def _load_yaml_file(yaml_file: Text) -> Dict: """ load yaml file and check file content format """ - with io.open(yaml_file, "r", encoding="utf-8") as stream: + with open(yaml_file, encoding="utf-8") as stream: try: yaml_content = yaml.load(stream) except yaml.YAMLError as ex: @@ -43,7 +42,7 @@ def _load_yaml_file(yaml_file: Text) -> Dict: def _load_json_file(json_file: Text) -> Dict: """ load json file and check file content format """ - with io.open(json_file, encoding="utf-8") as data_file: + with open(json_file, encoding="utf-8") as data_file: try: json_content = json.load(data_file) except json.JSONDecodeError as ex: @@ -128,7 +127,7 @@ def load_dot_env_file(dot_env_path: Text) -> Dict: logger.info(f"Loading environment variables from {dot_env_path}") env_variables_mapping = {} - with io.open(dot_env_path, "r", encoding="utf-8") as fp: + with open(dot_env_path, encoding="utf-8") as fp: for line in fp: # maxsplit=1 if "=" in line: @@ -182,7 +181,7 @@ def load_csv_file(csv_file: Text) -> List[Dict]: csv_content_list = [] - with io.open(csv_file, encoding="utf-8") as csvfile: + with open(csv_file, encoding="utf-8") as csvfile: reader = csv.DictReader(csvfile) for row in reader: csv_content_list.append(row) From c02ba2a85a0fbd867251dde8862e8b435ebf7fea Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 29 Jun 2020 15:20:37 +0800 Subject: [PATCH 05/13] change: open file in binary mode --- docs/CHANGELOG.md | 1 + httprunner/ext/har2case/utils.py | 4 ++-- httprunner/loader.py | 16 ++++++++-------- httprunner/scaffold.py | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index ec3fce4a..3206dd26 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -10,6 +10,7 @@ **Changed** - change: import locust at beginning to monkey patch all modules +- change: open file in binary mode ## 3.1.1 (2020-06-23) diff --git a/httprunner/ext/har2case/utils.py b/httprunner/ext/har2case/utils.py index 110f8b40..ead83b30 100644 --- a/httprunner/ext/har2case/utils.py +++ b/httprunner/ext/har2case/utils.py @@ -27,9 +27,9 @@ def load_har_log_entries(file_path): ] """ - with open(file_path, encoding="utf-8") as f: + with open(file_path, mode="rb") as f: try: - content_json = json.loads(f.read()) + content_json = json.load(f) return content_json["log"]["entries"] except (TypeError, JSONDecodeError) as ex: logger.error(f"failed to load HAR file {file_path}: {ex}") diff --git a/httprunner/loader.py b/httprunner/loader.py index b389c716..8a28f0ed 100644 --- a/httprunner/loader.py +++ b/httprunner/loader.py @@ -28,7 +28,7 @@ project_meta: Union[ProjectMeta, None] = None def _load_yaml_file(yaml_file: Text) -> Dict: """ load yaml file and check file content format """ - with open(yaml_file, encoding="utf-8") as stream: + with open(yaml_file, mode="rb") as stream: try: yaml_content = yaml.load(stream) except yaml.YAMLError as ex: @@ -42,7 +42,7 @@ def _load_yaml_file(yaml_file: Text) -> Dict: def _load_json_file(json_file: Text) -> Dict: """ load json file and check file content format """ - with open(json_file, encoding="utf-8") as data_file: + with open(json_file, mode="rb") as data_file: try: json_content = json.load(data_file) except json.JSONDecodeError as ex: @@ -127,17 +127,17 @@ def load_dot_env_file(dot_env_path: Text) -> Dict: logger.info(f"Loading environment variables from {dot_env_path}") env_variables_mapping = {} - with open(dot_env_path, encoding="utf-8") as fp: + with open(dot_env_path, mode="rb") as fp: for line in fp: # maxsplit=1 - if "=" in line: - variable, value = line.split("=", 1) - elif ":" in line: - variable, value = line.split(":", 1) + if b"=" in line: + variable, value = line.split(b"=", 1) + elif b":" in line: + variable, value = line.split(b":", 1) else: raise exceptions.FileFormatError(".env format error") - env_variables_mapping[variable.strip()] = value.strip() + env_variables_mapping[variable.strip().decode("utf-8")] = value.strip().decode("utf-8") utils.set_os_environ(env_variables_mapping) return env_variables_mapping diff --git a/httprunner/scaffold.py b/httprunner/scaffold.py index 07d1f33a..3f42f32d 100644 --- a/httprunner/scaffold.py +++ b/httprunner/scaffold.py @@ -49,7 +49,7 @@ def create_scaffold(project_name): print(msg) def create_file(path, file_content=""): - with open(path, "w") as f: + with open(path, "w", encoding="utf-8") as f: f.write(file_content) msg = f"created file: {path}" print(msg) From d6be5215d1af54ba1ed422d6520642a1ab48c9f6 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 29 Jun 2020 17:16:51 +0800 Subject: [PATCH 06/13] change: trigger github actions on push and pull_request --- .github/workflows/integration_test.yml | 2 +- .github/workflows/unittest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index 4948e7cf..0f53e94e 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -1,6 +1,6 @@ name: integration_test -on: [push] +on: [push, pull_request] jobs: integration_test: diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml index c6b705d1..8b507ee8 100644 --- a/.github/workflows/unittest.yml +++ b/.github/workflows/unittest.yml @@ -1,6 +1,6 @@ name: unittest -on: [push] +on: [push, pull_request] jobs: unittest: From 74c0f3e86d57c80e191c37b660a6b72017f6c219 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 29 Jun 2020 18:24:24 +0800 Subject: [PATCH 07/13] fix: mishandling of request header `Content-Length` for GET method --- docs/CHANGELOG.md | 1 + httprunner/models.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3206dd26..164235e0 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -6,6 +6,7 @@ - fix: missing setup/teardown hooks for referenced testcase - fix: compatibility for `black` on Android termux that does not support multiprocessing well +- fix: mishandling of request header `Content-Length` for GET method **Changed** diff --git a/httprunner/models.py b/httprunner/models.py index 775a7a75..51264c33 100644 --- a/httprunner/models.py +++ b/httprunner/models.py @@ -51,8 +51,8 @@ class TRequest(BaseModel): url: Url params: Dict[Text, Text] = {} headers: Headers = {} - req_json: Union[Dict, List] = Field({}, alias="json") - data: Union[Text, Dict[Text, Any]] = "" + req_json: Union[Dict, List] = Field(None, alias="json") + data: Union[Text, Dict[Text, Any]] = None cookies: Cookies = {} timeout: float = 120 allow_redirects: bool = True From 36b899b8b412f16e0fa1de6724a10a363cdb54f1 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 29 Jun 2020 18:26:44 +0800 Subject: [PATCH 08/13] change: github action trigger event --- .github/workflows/integration_test.yml | 2 +- .github/workflows/unittest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index 0f53e94e..4948e7cf 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -1,6 +1,6 @@ name: integration_test -on: [push, pull_request] +on: [push] jobs: integration_test: diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml index 8b507ee8..c6b705d1 100644 --- a/.github/workflows/unittest.yml +++ b/.github/workflows/unittest.yml @@ -1,6 +1,6 @@ name: unittest -on: [push, pull_request] +on: [push] jobs: unittest: From 9bcacd8ccc17da44179745405210cf39389e0c96 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 29 Jun 2020 18:42:20 +0800 Subject: [PATCH 09/13] change: github action trigger event --- .github/workflows/integration_test.yml | 2 +- .github/workflows/unittest.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index 4948e7cf..0f53e94e 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -1,6 +1,6 @@ name: integration_test -on: [push] +on: [push, pull_request] jobs: integration_test: diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml index c6b705d1..8b507ee8 100644 --- a/.github/workflows/unittest.yml +++ b/.github/workflows/unittest.yml @@ -1,6 +1,6 @@ name: unittest -on: [push] +on: [push, pull_request] jobs: unittest: From d9247261030f2ee0c61b28218a8be1f48192e3cd Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 29 Jun 2020 18:49:32 +0800 Subject: [PATCH 10/13] tests: update version --- examples/httpbin/basic_test.py | 2 +- examples/httpbin/hooks_test.py | 2 +- examples/httpbin/load_image_test.py | 2 +- examples/httpbin/upload_test.py | 2 +- examples/httpbin/validate_test.py | 2 +- .../demo_testsuite_yml/request_with_functions_test.py | 2 +- .../request_with_testcase_reference_test.py | 4 +++- examples/postman_echo/request_methods/hardcode_test.py | 2 +- .../request_methods/request_with_variables_test.py | 2 +- .../request_methods/validate_with_functions_test.py | 2 +- .../request_methods/validate_with_variables_test.py | 2 +- httprunner/loader.py | 4 +++- 12 files changed, 16 insertions(+), 12 deletions(-) diff --git a/examples/httpbin/basic_test.py b/examples/httpbin/basic_test.py index 3f912332..f541798f 100644 --- a/examples/httpbin/basic_test.py +++ b/examples/httpbin/basic_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: basic.yml from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase diff --git a/examples/httpbin/hooks_test.py b/examples/httpbin/hooks_test.py index b9d12e1a..36d134e0 100644 --- a/examples/httpbin/hooks_test.py +++ b/examples/httpbin/hooks_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: hooks.yml from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase diff --git a/examples/httpbin/load_image_test.py b/examples/httpbin/load_image_test.py index ecbd0aa5..47b05af1 100644 --- a/examples/httpbin/load_image_test.py +++ b/examples/httpbin/load_image_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: load_image.yml from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase diff --git a/examples/httpbin/upload_test.py b/examples/httpbin/upload_test.py index 826aae8f..cdec89fd 100644 --- a/examples/httpbin/upload_test.py +++ b/examples/httpbin/upload_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: upload.yml from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase diff --git a/examples/httpbin/validate_test.py b/examples/httpbin/validate_test.py index bbbc58e8..ed15c14d 100644 --- a/examples/httpbin/validate_test.py +++ b/examples/httpbin/validate_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: validate.yml from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase diff --git a/examples/postman_echo/request_methods/demo_testsuite_yml/request_with_functions_test.py b/examples/postman_echo/request_methods/demo_testsuite_yml/request_with_functions_test.py index 7030055a..50eb0cc8 100644 --- a/examples/postman_echo/request_methods/demo_testsuite_yml/request_with_functions_test.py +++ b/examples/postman_echo/request_methods/demo_testsuite_yml/request_with_functions_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: request_methods/request_with_functions.yml from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase diff --git a/examples/postman_echo/request_methods/demo_testsuite_yml/request_with_testcase_reference_test.py b/examples/postman_echo/request_methods/demo_testsuite_yml/request_with_testcase_reference_test.py index 63a5b73e..2d131814 100644 --- a/examples/postman_echo/request_methods/demo_testsuite_yml/request_with_testcase_reference_test.py +++ b/examples/postman_echo/request_methods/demo_testsuite_yml/request_with_testcase_reference_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: request_methods/request_with_testcase_reference.yml import sys @@ -35,7 +35,9 @@ class TestCaseRequestWithTestcaseReference(HttpRunner): .with_variables( **{"foo1": "testcase_ref_bar1", "expect_foo1": "testcase_ref_bar1"} ) + .setup_hook("${sleep(0.1)}") .call(RequestWithFunctions) + .teardown_hook("${sleep(0.2)}") .export(*["foo3"]) ), Step( diff --git a/examples/postman_echo/request_methods/hardcode_test.py b/examples/postman_echo/request_methods/hardcode_test.py index 95e1e421..70e5e3c9 100644 --- a/examples/postman_echo/request_methods/hardcode_test.py +++ b/examples/postman_echo/request_methods/hardcode_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: request_methods/hardcode.yml from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase diff --git a/examples/postman_echo/request_methods/request_with_variables_test.py b/examples/postman_echo/request_methods/request_with_variables_test.py index 74f38b37..cacc4621 100644 --- a/examples/postman_echo/request_methods/request_with_variables_test.py +++ b/examples/postman_echo/request_methods/request_with_variables_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: request_methods/request_with_variables.yml from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase diff --git a/examples/postman_echo/request_methods/validate_with_functions_test.py b/examples/postman_echo/request_methods/validate_with_functions_test.py index 68179d7b..4b67bba5 100644 --- a/examples/postman_echo/request_methods/validate_with_functions_test.py +++ b/examples/postman_echo/request_methods/validate_with_functions_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: request_methods/validate_with_functions.yml from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase diff --git a/examples/postman_echo/request_methods/validate_with_variables_test.py b/examples/postman_echo/request_methods/validate_with_variables_test.py index 83225fa5..07f6d5b3 100644 --- a/examples/postman_echo/request_methods/validate_with_variables_test.py +++ b/examples/postman_echo/request_methods/validate_with_variables_test.py @@ -1,4 +1,4 @@ -# NOTE: Generated By HttpRunner v3.1.0 +# NOTE: Generated By HttpRunner v3.1.2 # FROM: request_methods/validate_with_variables.yml from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase diff --git a/httprunner/loader.py b/httprunner/loader.py index 8a28f0ed..afaae632 100644 --- a/httprunner/loader.py +++ b/httprunner/loader.py @@ -137,7 +137,9 @@ def load_dot_env_file(dot_env_path: Text) -> Dict: else: raise exceptions.FileFormatError(".env format error") - env_variables_mapping[variable.strip().decode("utf-8")] = value.strip().decode("utf-8") + env_variables_mapping[ + variable.strip().decode("utf-8") + ] = value.strip().decode("utf-8") utils.set_os_environ(env_variables_mapping) return env_variables_mapping From 289afe19a01ca1dc587b155f18aae07d3824c135 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 29 Jun 2020 19:08:39 +0800 Subject: [PATCH 11/13] test: add test for ResponseObject, #948 --- docs/CHANGELOG.md | 1 + httprunner/response.py | 3 +++ tests/response_test.py | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 tests/response_test.py diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 164235e0..5bd0fc5e 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -7,6 +7,7 @@ - fix: missing setup/teardown hooks for referenced testcase - fix: compatibility for `black` on Android termux that does not support multiprocessing well - fix: mishandling of request header `Content-Length` for GET method +- fix: validate with jmespath containing variable or function, e.g. `body.locations[$index].name` **Changed** diff --git a/httprunner/response.py b/httprunner/response.py index 1f110a26..6b129a97 100644 --- a/httprunner/response.py +++ b/httprunner/response.py @@ -171,6 +171,9 @@ class ResponseObject(object): functions_mapping: FunctionsMapping = None, ) -> NoReturn: + variables_mapping = variables_mapping or {} + functions_mapping = functions_mapping or {} + self.validation_results = {} if not validators: return diff --git a/tests/response_test.py b/tests/response_test.py new file mode 100644 index 00000000..f6f8e936 --- /dev/null +++ b/tests/response_test.py @@ -0,0 +1,39 @@ +import unittest + +import requests + +from httprunner.response import ResponseObject + + +class TestResponse(unittest.TestCase): + def setUp(self) -> None: + resp = requests.post( + "https://httpbin.org/anything", + json={ + "locations": [ + {"name": "Seattle", "state": "WA"}, + {"name": "New York", "state": "NY"}, + {"name": "Bellevue", "state": "WA"}, + {"name": "Olympia", "state": "WA"}, + ] + }, + ) + self.resp_obj = ResponseObject(resp) + + def test_extract(self): + extract_mapping = self.resp_obj.extract( + {"var_1": "body.json.locations[0]", "var_2": "body.json.locations[3].name"} + ) + self.assertEqual(extract_mapping["var_1"], {"name": "Seattle", "state": "WA"}) + self.assertEqual(extract_mapping["var_2"], "Olympia") + + def test_validate(self): + variables_mapping = {"index": 1} + self.resp_obj.validate( + [ + {"eq": ["body.json.locations[0].name", "Seattle"]}, + {"eq": ["body.json.locations[0]", {"name": "Seattle", "state": "WA"}]}, + {"eq": ["body.json.locations[$index].name", "New York"]}, + ], + variables_mapping=variables_mapping, + ) From 4f685a6d81fa50ce9e6f65106f8ded19bb187436 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 29 Jun 2020 20:25:19 +0800 Subject: [PATCH 12/13] test: update --- examples/httpbin/hooks.yml | 1 - examples/httpbin/hooks_test.py | 1 - 2 files changed, 2 deletions(-) diff --git a/examples/httpbin/hooks.yml b/examples/httpbin/hooks.yml index 250a7a8f..23f0ba57 100644 --- a/examples/httpbin/hooks.yml +++ b/examples/httpbin/hooks.yml @@ -33,5 +33,4 @@ teststeps: validate: - eq: ["status_code", 500] - eq: [headers."Content-Type", "html/text"] - - eq: [body.headers."Content-Type", "application/json"] - eq: [body.headers.Host, "127.0.0.1:8888"] diff --git a/examples/httpbin/hooks_test.py b/examples/httpbin/hooks_test.py index 36d134e0..86a1b0d7 100644 --- a/examples/httpbin/hooks_test.py +++ b/examples/httpbin/hooks_test.py @@ -26,7 +26,6 @@ class TestCaseHooks(HttpRunner): .validate() .assert_equal("status_code", 500) .assert_equal('headers."Content-Type"', "html/text") - .assert_equal('body.headers."Content-Type"', "application/json") .assert_equal("body.headers.Host", "127.0.0.1:8888") ), ] From 453e1a39c74b8127fadcf9e4eff04c9ff6081cef Mon Sep 17 00:00:00 2001 From: debugtalk Date: Mon, 29 Jun 2020 20:28:55 +0800 Subject: [PATCH 13/13] change: github action trigger event --- .github/workflows/integration_test.yml | 8 +++++++- .github/workflows/unittest.yml | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index 0f53e94e..bc5b0ed4 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -1,6 +1,12 @@ name: integration_test -on: [push, pull_request] +on: + push: + branches: + - master + pull_request: + branches: + - master jobs: integration_test: diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml index 8b507ee8..dddc5860 100644 --- a/.github/workflows/unittest.yml +++ b/.github/workflows/unittest.yml @@ -1,6 +1,12 @@ name: unittest -on: [push, pull_request] +on: + push: + branches: + - master + pull_request: + branches: + - master jobs: unittest: