From 6ea86ae95d000da118ae39caa4f0c9bc49c4a938 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Tue, 28 Aug 2018 14:35:26 +0800 Subject: [PATCH 1/2] add --dot-env-path back --- httprunner/api.py | 4 +++- httprunner/cli.py | 5 ++++- httprunner/loader.py | 15 +++++++++++---- tests/test_loader.py | 10 ++++++++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/httprunner/api.py b/httprunner/api.py index 2e87c5fe..b3356732 100644 --- a/httprunner/api.py +++ b/httprunner/api.py @@ -19,6 +19,7 @@ class HttpRunner(object): resultclass (class): HtmlTestResult or TextTestResult failfast (bool): False/True, stop the test run on the first error or failure. http_client_session (instance): requests.Session(), or locust.client.Session() instance. + dot_env_path (str): .env file path. Attributes: project_mapping (dict): save project loaded api/testcases, environments and debugtalk.py module. @@ -33,8 +34,9 @@ class HttpRunner(object): } """ + loader.dot_env_path = kwargs.pop("dot_env_path", None) + self.http_client_session = kwargs.pop("http_client_session", None) self.kwargs = kwargs - self.http_client_session = self.kwargs.pop("http_client_session", None) def load_tests(self, path_or_testcases): """ load testcases, extend and merge with api/testcase definitions. diff --git a/httprunner/cli.py b/httprunner/cli.py index fc15ab5b..ec645471 100644 --- a/httprunner/cli.py +++ b/httprunner/cli.py @@ -39,6 +39,9 @@ def main_hrun(): parser.add_argument( '--log-file', help="Write logs to specified file path.") + parser.add_argument( + '--dot-env-path', + help="Specify .env file path, which is useful for keeping sensitive data.") parser.add_argument( '--failfast', action='store_true', default=False, help="Stop the test run on the first error or failure.") @@ -75,7 +78,7 @@ def main_hrun(): create_scaffold(project_path) exit(0) - runner = HttpRunner(failfast=args.failfast).run(args.testset_paths) + runner = HttpRunner(failfast=args.failfast, dot_env_path=args.dot_env_path).run(args.testset_paths) if not args.no_html_report: runner.gen_html_report( diff --git a/httprunner/loader.py b/httprunner/loader.py index e17c46d4..ae6e5a85 100644 --- a/httprunner/loader.py +++ b/httprunner/loader.py @@ -24,6 +24,8 @@ project_mapping = { """ dict: save project loaded api/testcases definitions, environments and debugtalk.py module. """ +dot_env_path = None + testcases_cache_mapping = {} project_working_directory = os.getcwd() @@ -161,7 +163,8 @@ def load_folder_files(folder_path, recursive=True): def load_dot_env_file(): - """ load .env file, .env file should be located in project working directory. + """ load .env file, .env file should be located in project working directory by default. + If dot_env_path is specified, it will be loaded instead. Returns: dict: environment variables mapping @@ -176,10 +179,14 @@ def load_dot_env_file(): exceptions.FileFormatError: If env file format is invalid. """ - path = os.path.join(project_working_directory, ".env") + path = dot_env_path or os.path.join(project_working_directory, ".env") if not os.path.isfile(path): - logger.log_debug(".env file not exist in : {}".format(project_working_directory)) - return {} + if dot_env_path: + logger.log_error(".env file not exist: {}".format(dot_env_path)) + sys.exit(1) + else: + logger.log_debug(".env file not exist in: {}".format(project_working_directory)) + return {} logger.log_info("Loading environment variables from {}".format(path)) env_variables_mapping = {} diff --git a/tests/test_loader.py b/tests/test_loader.py index b6f08745..18e67d86 100644 --- a/tests/test_loader.py +++ b/tests/test_loader.py @@ -140,6 +140,16 @@ class TestFileLoader(unittest.TestCase): self.assertIn("PROJECT_KEY", env_variables_mapping) self.assertEqual(env_variables_mapping["UserName"], "debugtalk") + def test_load_custom_dot_env_file(self): + loader.project_working_directory = os.path.join( + os.getcwd(), "tests", + ) + loader.dot_env_path = "tests/data/test.env" + env_variables_mapping = loader.load_dot_env_file() + self.assertIn("PROJECT_KEY", env_variables_mapping) + self.assertEqual(env_variables_mapping["UserName"], "test") + loader.dot_env_path = None + def test_load_env_path_not_exist(self): loader.project_working_directory = os.path.join( os.getcwd(), "tests", "data", From c22651f43e3a7ea773eb1776db9e02653611c85d Mon Sep 17 00:00:00 2001 From: debugtalk Date: Thu, 30 Aug 2018 21:05:58 +0800 Subject: [PATCH 2/2] fix #361: parameters data error --- httprunner/api.py | 23 ++++++++++++----------- httprunner/loader.py | 2 ++ tests/test_api.py | 14 +++++++++++++- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/httprunner/api.py b/httprunner/api.py index b3356732..02bf9337 100644 --- a/httprunner/api.py +++ b/httprunner/api.py @@ -1,5 +1,6 @@ # encoding: utf-8 +import copy import os import unittest @@ -120,11 +121,8 @@ class HttpRunner(object): parsed_testcases_list = [] for testcase in testcases: - - config = testcase.setdefault("config", {}) - # parse config parameters - config_parameters = config.pop("parameters", []) + config_parameters = testcase.setdefault("config", {}).pop("parameters", []) cartesian_product_parameters_list = parser.parse_parameters( config_parameters, self.project_mapping["debugtalk"]["variables"], @@ -132,6 +130,9 @@ class HttpRunner(object): ) or [{}] for parameter_mapping in cartesian_product_parameters_list: + testcase_dict = copy.deepcopy(testcase) + config = testcase_dict.setdefault("config", {}) + # parse config variables raw_config_variables = config.get("variables", []) parsed_config_variables = parser.parse_data( @@ -150,25 +151,25 @@ class HttpRunner(object): config_variables = utils.override_mapping_list( config_variables, variables_mapping) - testcase["config"]["variables"] = config_variables + testcase_dict["config"]["variables"] = config_variables # parse config name - testcase["config"]["name"] = parser.parse_data( - testcase["config"].get("name", ""), + testcase_dict["config"]["name"] = parser.parse_data( + testcase_dict["config"].get("name", ""), config_variables, self.project_mapping["debugtalk"]["functions"] ) # parse config request - testcase["config"]["request"] = parser.parse_data( - testcase["config"].get("request", {}), + testcase_dict["config"]["request"] = parser.parse_data( + testcase_dict["config"].get("request", {}), config_variables, self.project_mapping["debugtalk"]["functions"] ) # put loaded project functions to config - testcase["config"]["functions"] = self.project_mapping["debugtalk"]["functions"] - parsed_testcases_list.append(testcase) + testcase_dict["config"]["functions"] = self.project_mapping["debugtalk"]["functions"] + parsed_testcases_list.append(testcase_dict) return parsed_testcases_list diff --git a/httprunner/loader.py b/httprunner/loader.py index ae6e5a85..f4c709ec 100644 --- a/httprunner/loader.py +++ b/httprunner/loader.py @@ -268,6 +268,8 @@ def load_python_module(module): if validator.is_function((name, item)): debugtalk_module["functions"][name] = item elif validator.is_variable((name, item)): + if isinstance(item, tuple): + continue debugtalk_module["variables"][name] = item else: pass diff --git a/tests/test_api.py b/tests/test_api.py index a83a4cae..fcb7feaa 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -321,13 +321,21 @@ class TestHttpRunner(ApiServerUnittest): self.assertIn("token", summary["details"][0]["in_out"]["out"]) self.assertGreater(len(summary["details"][0]["in_out"]["in"]), 7) - def test_run_testset_with_parameters(self): + def test_run_testcase_with_parameters(self): testcase_file_path = os.path.join( os.getcwd(), 'tests/data/demo_parameters.yml') runner = HttpRunner().run(testcase_file_path) summary = runner.summary self.assertEqual( summary["details"][0]["in_out"]["in"]["user_agent"], + "iOS/10.1" + ) + self.assertEqual( + summary["details"][2]["in_out"]["in"]["user_agent"], + "iOS/10.2" + ) + self.assertEqual( + summary["details"][4]["in_out"]["in"]["user_agent"], "iOS/10.3" ) self.assertTrue(summary["success"]) @@ -362,6 +370,10 @@ class TestHttpRunner(ApiServerUnittest): self.assertEqual(len(parsed_testcases), 2 * 2) self.assertEqual( parsed_testcases[0]["config"]["request"]["base_url"], + '$BASE_URL' + ) + self.assertEqual( + parsed_testcases[0]["config"]["variables"]["BASE_URL"], 'http://127.0.0.1:5000' ) self.assertIsInstance(parsed_testcases, list)