import os import time import requests from httprunner import exception, response, runner, testcase, utils from httprunner.context import Context from tests.base import ApiServerUnittest class VariableBindsUnittest(ApiServerUnittest): def setUp(self): self.context = Context() testcase_file_path = os.path.join(os.getcwd(), 'tests/data/demo_binds.yml') self.testcases = testcase.load_file(testcase_file_path) def test_context_init_functions(self): self.assertIn("get_timestamp", self.context.testset_functions_config) self.assertIn("gen_random_string", self.context.testset_functions_config) variables = [ {"random": "${gen_random_string(5)}"}, {"timestamp10": "${get_timestamp(10)}"} ] self.context.bind_variables(variables) context_variables = self.context.testcase_variables_mapping self.assertEqual(len(context_variables["random"]), 5) self.assertEqual(len(context_variables["timestamp10"]), 10) def test_context_bind_testset_variables(self): # testcase in JSON format testcase1 = { "variables": [ {"GLOBAL_TOKEN": "debugtalk"}, {"token": "$GLOBAL_TOKEN"} ] } # testcase in YAML format testcase2 = self.testcases["bind_variables"] for testcase in [testcase1, testcase2]: variables = testcase['variables'] self.context.bind_variables(variables, level="testset") testset_variables = self.context.testset_shared_variables_mapping testcase_variables = self.context.testcase_variables_mapping self.assertIn("GLOBAL_TOKEN", testset_variables) self.assertIn("GLOBAL_TOKEN", testcase_variables) self.assertEqual(testset_variables["GLOBAL_TOKEN"], "debugtalk") self.assertIn("token", testset_variables) self.assertIn("token", testcase_variables) self.assertEqual(testset_variables["token"], "debugtalk") def test_context_bind_testcase_variables(self): testcase1 = { "variables": [ {"GLOBAL_TOKEN": "debugtalk"}, {"token": "$GLOBAL_TOKEN"} ] } testcase2 = self.testcases["bind_variables"] for testcase in [testcase1, testcase2]: variables = testcase['variables'] self.context.bind_variables(variables) testset_variables = self.context.testset_shared_variables_mapping testcase_variables = self.context.testcase_variables_mapping self.assertNotIn("GLOBAL_TOKEN", testset_variables) self.assertIn("GLOBAL_TOKEN", testcase_variables) self.assertEqual(testcase_variables["GLOBAL_TOKEN"], "debugtalk") self.assertNotIn("token", testset_variables) self.assertIn("token", testcase_variables) self.assertEqual(testcase_variables["token"], "debugtalk") def test_context_bind_lambda_functions(self): testcase1 = { "function_binds": { "add_one": lambda x: x + 1, "add_two_nums": lambda x, y: x + y }, "variables": [ {"add1": "${add_one(2)}"}, {"sum2nums": "${add_two_nums(2,3)}"} ] } testcase2 = self.testcases["bind_lambda_functions"] for testcase in [testcase1, testcase2]: function_binds = testcase.get('function_binds', {}) self.context.bind_functions(function_binds) variables = testcase['variables'] self.context.bind_variables(variables) context_variables = self.context.testcase_variables_mapping self.assertIn("add1", context_variables) self.assertEqual(context_variables["add1"], 3) self.assertIn("sum2nums", context_variables) self.assertEqual(context_variables["sum2nums"], 5) def test_call_builtin_functions(self): testcase1 = { "variables": [ {"length": "${len(debugtalk)}"}, {"smallest": "${min(2, 3, 8)}"}, {"largest": "${max(2, 3, 8)}"} ] } testcase2 = self.testcases["builtin_functions"] for testcase in [testcase1, testcase2]: variables = testcase['variables'] self.context.bind_variables(variables) context_variables = self.context.testcase_variables_mapping self.assertEqual(context_variables["length"], 9) self.assertEqual(context_variables["smallest"], 2) self.assertEqual(context_variables["largest"], 8) def test_context_bind_lambda_functions_with_import(self): testcase1 = { "requires": ["random", "string", "hashlib"], "function_binds": { "gen_random_string": "lambda str_len: ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(str_len))", "gen_md5": "lambda *str_args: hashlib.md5(''.join(str_args).encode('utf-8')).hexdigest()" }, "variables": [ {"TOKEN": "debugtalk"}, {"random": "${gen_random_string(5)}"}, {"data": '{"name": "user", "password": "123456"}'}, {"authorization": "${gen_md5($TOKEN, $data, $random)}"} ] } testcase2 = self.testcases["bind_lambda_functions_with_import"] for testcase in [testcase1, testcase2]: requires = testcase.get('requires', []) self.context.import_requires(requires) function_binds = testcase.get('function_binds', {}) self.context.bind_functions(function_binds) variables = testcase['variables'] self.context.bind_variables(variables) context_variables = self.context.testcase_variables_mapping self.assertIn("TOKEN", context_variables) TOKEN = context_variables["TOKEN"] self.assertEqual(TOKEN, "debugtalk") self.assertIn("random", context_variables) self.assertIsInstance(context_variables["random"], str) self.assertEqual(len(context_variables["random"]), 5) random = context_variables["random"] self.assertIn("data", context_variables) data = context_variables["data"] self.assertIn("authorization", context_variables) self.assertEqual(len(context_variables["authorization"]), 32) authorization = context_variables["authorization"] self.assertEqual(utils.gen_md5(TOKEN, data, random), authorization) def test_import_module_items(self): testcase1 = { "import_module_items": ["tests.data.debugtalk"], "variables": [ {"TOKEN": "debugtalk"}, {"random": "${gen_random_string(5)}"}, {"data": '{"name": "user", "password": "123456"}'}, {"authorization": "${gen_md5($TOKEN, $data, $random)}"} ] } testcase2 = self.testcases["bind_module_functions"] for testcase in [testcase1, testcase2]: module_items = testcase.get('import_module_items', []) self.context.import_module_items(module_items) variables = testcase['variables'] self.context.bind_variables(variables) context_variables = self.context.testcase_variables_mapping self.assertIn("TOKEN", context_variables) TOKEN = context_variables["TOKEN"] self.assertEqual(TOKEN, "debugtalk") self.assertIn("random", context_variables) self.assertIsInstance(context_variables["random"], str) self.assertEqual(len(context_variables["random"]), 5) random = context_variables["random"] self.assertIn("data", context_variables) data = context_variables["data"] self.assertIn("authorization", context_variables) self.assertEqual(len(context_variables["authorization"]), 32) authorization = context_variables["authorization"] self.assertEqual(utils.gen_md5(TOKEN, data, random), authorization) self.assertIn("SECRET_KEY", context_variables) SECRET_KEY = context_variables["SECRET_KEY"] self.assertEqual(SECRET_KEY, "DebugTalk") def test_get_parsed_request(self): test_runner = runner.Runner() testcase = { "import_module_items": ["tests.data.debugtalk"], "variables": [ {"TOKEN": "debugtalk"}, {"random": "${gen_random_string(5)}"}, {"data": '{"name": "user", "password": "123456"}'}, {"authorization": "${gen_md5($TOKEN, $data, $random)}"} ], "request": { "url": "http://127.0.0.1:5000/api/users/1000", "METHOD": "POST", "Headers": { "Content-Type": "application/json", "authorization": "$authorization", "random": "$random", "SECRET_KEY": "$SECRET_KEY" }, "Data": "$data" } } parsed_request = test_runner.init_config(testcase, level="testcase") self.assertIn("authorization", parsed_request["headers"]) self.assertEqual(len(parsed_request["headers"]["authorization"]), 32) self.assertIn("random", parsed_request["headers"]) self.assertEqual(len(parsed_request["headers"]["random"]), 5) self.assertIn("data", parsed_request) self.assertEqual(parsed_request["data"], testcase["variables"][2]["data"]) self.assertEqual(parsed_request["headers"]["secret_key"], "DebugTalk") def test_exec_content_functions(self): test_runner = runner.Runner() content = "${teardown_hook_sleep_1_secs(1)}" start_time = time.time() test_runner.context.eval_content(content) end_time = time.time() elapsed_time = end_time - start_time self.assertGreater(elapsed_time, 1) def test_do_validation(self): self.context.do_validation( {"check": "check", "check_value": 1, "expect": 1, "comparator": "eq"} ) self.context.do_validation( {"check": "check", "check_value": "abc", "expect": "abc", "comparator": "=="} ) config_dict = { "path": 'tests/data/demo_testset_hardcode.yml' } self.context.config_context(config_dict, "testset") self.context.do_validation( {"check": "status_code", "check_value": "201", "expect": 3, "comparator": "sum_status_code"} ) def test_validate(self): url = "http://127.0.0.1:5000/" resp = requests.get(url) resp_obj = response.ResponseObject(resp) validators = [ {"eq": ["$resp_status_code", 201]}, {"check": "$resp_status_code", "comparator": "eq", "expect": 201}, {"check": "$resp_body_success", "comparator": "eq", "expect": True} ] variables = [ {"resp_status_code": 200}, {"resp_body_success": True} ] self.context.bind_variables(variables) with self.assertRaises(exception.ValidationError): self.context.validate(validators, resp_obj) variables = [ {"resp_status_code": 201}, {"resp_body_success": True} ] self.context.bind_variables(variables) self.assertTrue(self.context.validate(validators, resp_obj)) def test_validate_exception(self): url = "http://127.0.0.1:5000/" resp = requests.get(url) resp_obj = response.ResponseObject(resp) # expected value missed in validators validators = [ {"eq": ["$resp_status_code", 201]}, {"check": "$resp_status_code", "comparator": "eq", "expect": 201}, {"check": "$resp_body_success", "comparator": "eq", "expect": True} ] variables = [] self.context.bind_variables(variables) with self.assertRaises(exception.ParamsError): self.context.validate(validators, resp_obj) # expected value missed in variables mapping variables = [ {"resp_status_code": 200} ] self.context.bind_variables(variables) with self.assertRaises(exception.ValidationError): self.context.validate(validators, resp_obj)