feat: implement lazy parser

This commit is contained in:
debugtalk
2019-04-04 01:21:08 +08:00
parent e8c5e54eb2
commit d7b76b2fcc
11 changed files with 949 additions and 569 deletions

View File

@@ -60,9 +60,16 @@ class HttpRunner(object):
if "config" in test_dict: if "config" in test_dict:
# run nested testcase # run nested testcase
test.__doc__ = test_dict["config"].get("name") test.__doc__ = test_dict["config"].get("name")
variables = test_dict["config"].get("variables", {})
else: else:
# run api test # run api test
test.__doc__ = test_dict.get("name") test.__doc__ = test_dict.get("name")
variables = test_dict.get("variables", {})
if isinstance(test.__doc__, parser.LazyString):
parsed_variables = parser.parse_variables_mapping(variables, ignore=True)
test.__doc__ = parser.parse_lazy_data(
test.__doc__, parsed_variables)
return test return test

View File

@@ -36,16 +36,14 @@ class SessionContext(object):
""" """
variables_mapping = variables_mapping or {} variables_mapping = variables_mapping or {}
variables_mapping = utils.ensure_mapping_format(variables_mapping) variables_mapping = utils.ensure_mapping_format(variables_mapping)
variables_mapping.update(self.session_variables_mapping)
parsed_variables_mapping = parser.parse_variables_mapping(variables_mapping)
self.test_variables_mapping = {} self.test_variables_mapping = {}
# priority: extracted variable > teststep variable # priority: extracted variable > teststep variable
self.test_variables_mapping.update(variables_mapping) self.test_variables_mapping.update(parsed_variables_mapping)
self.test_variables_mapping.update(self.session_variables_mapping) self.test_variables_mapping.update(self.session_variables_mapping)
for variable_name, variable_value in variables_mapping.items():
variable_value = self.eval_content(variable_value)
self.update_test_variables(variable_name, variable_value)
def update_test_variables(self, variable_name, variable_value): def update_test_variables(self, variable_name, variable_value):
""" update test variables, these variables are only valid in the current test. """ update test variables, these variables are only valid in the current test.
""" """
@@ -63,11 +61,7 @@ class SessionContext(object):
""" evaluate content recursively, take effect on each variable and function in content. """ evaluate content recursively, take effect on each variable and function in content.
content may be in any data structure, include dict, list, tuple, number, string, etc. content may be in any data structure, include dict, list, tuple, number, string, etc.
""" """
return parser.parse_data( return parser.parse_lazy_data(content, self.test_variables_mapping)
content,
self.test_variables_mapping,
self.FUNCTIONS_MAPPING
)
def __eval_check_item(self, validator, resp_obj): def __eval_check_item(self, validator, resp_obj):
""" evaluate check item in validator. """ evaluate check item in validator.
@@ -95,10 +89,8 @@ class SessionContext(object):
# 3, dict or list, maybe containing variable/function reference, e.g. {"var": "$abc"} # 3, dict or list, maybe containing variable/function reference, e.g. {"var": "$abc"}
# 4, string joined by delimiter. e.g. "status_code", "headers.content-type" # 4, string joined by delimiter. e.g. "status_code", "headers.content-type"
# 5, regex string, e.g. "LB[\d]*(.*)RB[\d]*" # 5, regex string, e.g. "LB[\d]*(.*)RB[\d]*"
if isinstance(check_item, (dict, list)) \ if isinstance(check_item, (dict, list)) \
or parser.extract_variables(check_item) \ or isinstance(check_item, parser.LazyString):
or parser.extract_functions(check_item):
# format 1/2/3 # format 1/2/3
check_value = self.eval_content(check_item) check_value = self.eval_content(check_item)
else: else:

File diff suppressed because it is too large Load Diff

View File

@@ -199,7 +199,9 @@ class Runner(object):
self.session_context.init_test_variables(test_variables) self.session_context.init_test_variables(test_variables)
# teststep name # teststep name
test_name = test_dict.get("name", "") test_name = self.session_context.eval_content(test_dict.get("name", ""))
# TODO: refactor
self.http_client_session.base_url = self.session_context.eval_content(test_dict.get("base_url", ""))
# parse test request # parse test request
raw_request = test_dict.get('request', {}) raw_request = test_dict.get('request', {})
@@ -254,7 +256,6 @@ class Runner(object):
validators = test_dict.get("validate", []) validators = test_dict.get("validate", [])
try: try:
self.session_context.validate(validators, resp_obj) self.session_context.validate(validators, resp_obj)
except (exceptions.ParamsError, exceptions.ValidationFailure, exceptions.ExtractFailure): except (exceptions.ParamsError, exceptions.ValidationFailure, exceptions.ExtractFailure):
err_msg = "{} DETAILED REQUEST & RESPONSE {}\n".format("*" * 32, "*" * 32) err_msg = "{} DETAILED REQUEST & RESPONSE {}\n".format("*" * 32, "*" * 32)

View File

@@ -0,0 +1,13 @@
- config:
name: basic test with httpbin
base_url: https://httpbin.org/
verify: False
- test:
name: headers
request:
url: /headers
method: GET
validate:
- eq: ["status_code", 200]
- eq: [content.headers.Host, "httpbin.org"]

View File

@@ -1,8 +1,9 @@
- config: - config:
name: "123$var_a" name: "123t$var_a"
variables: variables:
var_a: 0 var_a: 1
var_c: "${sum_two(1, 2)}" var_b: 2
var_c: "${sum_two($var_a, $var_b)}"
var_d: "${gen_random_string(5)}" var_d: "${gen_random_string(5)}"
var_e: $var_d var_e: $var_d
PROJECT_KEY: ${ENV(PROJECT_KEY)} PROJECT_KEY: ${ENV(PROJECT_KEY)}

View File

@@ -589,7 +589,7 @@ class TestApi(ApiServerUnittest):
self.assertEqual(test_dict1["name"], "get token (setup)") self.assertEqual(test_dict1["name"], "get token (setup)")
self.assertNotIn("api_def", test_dict1) self.assertNotIn("api_def", test_dict1)
self.assertEqual(test_dict1["variables"]["device_sn"], "TESTCASE_SETUP_XXX") self.assertEqual(test_dict1["variables"]["device_sn"], "TESTCASE_SETUP_XXX")
self.assertEqual(test_dict1["request"]["url"], "http://127.0.0.1:5000/api/get-token") self.assertEqual(test_dict1["request"]["url"], "/api/get-token")
self.assertEqual(test_dict1["request"]["verify"], False) self.assertEqual(test_dict1["request"]["verify"], False)
test_dict2 = parsed_testcases[0]["teststeps"][1] test_dict2 = parsed_testcases[0]["teststeps"][1]
@@ -696,17 +696,14 @@ class TestApi(ApiServerUnittest):
self.assertEqual(len(parsed_testcases[0]["teststeps"]), 4) self.assertEqual(len(parsed_testcases[0]["teststeps"]), 4)
testcase1 = parsed_testcases[0]["teststeps"][0] testcase1 = parsed_testcases[0]["teststeps"][0]
self.assertIn("setup and reset all (override)", testcase1["config"]["name"]) self.assertIn("setup and reset all (override)", testcase1["config"]["name"].raw_string)
self.assertEqual(testcase1["teststeps"][0]["variables"]["var_c"], testcase1["teststeps"][0]["variables"]["var_d"]) teststeps = testcase1["teststeps"]
self.assertEqual(testcase1["teststeps"][0]["variables"]["var_a"], testcase1["teststeps"][0]["variables"]["var_b"])
self.assertNotEqual(testcase1["teststeps"][0]["variables"]["var_a"], testcase1["teststeps"][0]["variables"]["var_c"])
self.assertNotIn("testcase_def", testcase1) self.assertNotIn("testcase_def", testcase1)
self.assertEqual(len(testcase1["teststeps"]), 2) self.assertEqual(len(teststeps), 2)
self.assertEqual( self.assertEqual(
testcase1["teststeps"][0]["request"]["url"], teststeps[0]["request"]["url"],
"http://127.0.0.1:5000/api/get-token" "/api/get-token"
) )
self.assertEqual(len(testcase1["teststeps"][0]["variables"]["device_sn"]), 15)
def test_testsuite_add_tests(self): def test_testsuite_add_tests(self):
testcase_path = "tests/testsuites/create_users.yml" testcase_path = "tests/testsuites/create_users.yml"
@@ -718,7 +715,7 @@ class TestApi(ApiServerUnittest):
self.assertEqual(len(test_suite._tests), 2) self.assertEqual(len(test_suite._tests), 2)
tests = test_suite._tests[0].teststeps tests = test_suite._tests[0].teststeps
self.assertIn("setup and reset all (override)", tests[0]["config"]["name"]) self.assertIn("setup and reset all (override)", tests[0]["config"]["name"].raw_string)
def test_testsuite_run_suite(self): def test_testsuite_run_suite(self):
testcase_path = "tests/testsuites/create_users.yml" testcase_path = "tests/testsuites/create_users.yml"

View File

@@ -2,8 +2,8 @@ import os
import time import time
import requests import requests
from httprunner import context, exceptions, loader, response, utils from httprunner import context, exceptions, loader, parser, response, utils
from tests.base import ApiServerUnittest from tests.base import ApiServerUnittest, gen_md5, gen_random_string
class TestContext(ApiServerUnittest): class TestContext(ApiServerUnittest):
@@ -11,8 +11,9 @@ class TestContext(ApiServerUnittest):
def setUp(self): def setUp(self):
loader.load_project_tests(os.path.join(os.getcwd(), "tests")) loader.load_project_tests(os.path.join(os.getcwd(), "tests"))
project_mapping = loader.project_mapping project_mapping = loader.project_mapping
self.functions = project_mapping["functions"]
self.context = context.SessionContext( self.context = context.SessionContext(
functions=project_mapping["functions"], functions=self.functions,
variables={"SECRET_KEY": "DebugTalk"} variables={"SECRET_KEY": "DebugTalk"}
) )
@@ -30,16 +31,24 @@ class TestContext(ApiServerUnittest):
variables = { variables = {
"random": "${gen_random_string($num)}", "random": "${gen_random_string($num)}",
"authorization": "${gen_md5($TOKEN, $data, $random)}", "authorization": "${gen_md5($TOKEN, $data, $random)}",
"data": '{"name": "$username", "password": "123456"}', "data": "$username",
# TODO: escape '{' and '}'
# "data": '{"name": "$username", "password": "123456"}',
"TOKEN": "debugtalk", "TOKEN": "debugtalk",
"username": "user1", "username": "user1",
"num": 6 "num": 6
} }
functions = {
"gen_random_string": gen_random_string,
"gen_md5": gen_md5
}
variables = parser.prepare_lazy_data(variables, functions, variables.keys())
variables = parser.parse_variables_mapping(variables)
self.context.init_test_variables(variables) self.context.init_test_variables(variables)
variables_mapping = self.context.test_variables_mapping variables_mapping = self.context.test_variables_mapping
self.assertEqual(len(variables_mapping["random"]), 6) self.assertEqual(len(variables_mapping["random"]), 6)
self.assertEqual(len(variables_mapping["authorization"]), 32) self.assertEqual(len(variables_mapping["authorization"]), 32)
self.assertEqual(variables_mapping["data"], '{"name": "user1", "password": "123456"}') self.assertEqual(variables_mapping["data"], 'user1')
def test_update_seesion_variables(self): def test_update_seesion_variables(self):
self.context.update_session_variables({"TOKEN": "debugtalk"}) self.context.update_session_variables({"TOKEN": "debugtalk"})
@@ -49,14 +58,17 @@ class TestContext(ApiServerUnittest):
) )
def test_eval_content_functions(self): def test_eval_content_functions(self):
content = "${sleep_N_secs(1)}" content = parser.prepare_lazy_data("${sleep_N_secs(1)}", self.functions)
start_time = time.time() start_time = time.time()
self.context.eval_content(content) self.context.eval_content(content)
elapsed_time = time.time() - start_time elapsed_time = time.time() - start_time
self.assertGreater(elapsed_time, 1) self.assertGreater(elapsed_time, 1)
def test_eval_content_variables(self): def test_eval_content_variables(self):
content = "abc$SECRET_KEY" variables = {
"SECRET_KEY": "DebugTalk"
}
content = parser.prepare_lazy_data("abc$SECRET_KEY", {}, variables.keys())
self.assertEqual( self.assertEqual(
self.context.eval_content(content), self.context.eval_content(content),
"abcDebugTalk" "abcDebugTalk"
@@ -76,7 +88,12 @@ class TestContext(ApiServerUnittest):
"authorization": "${gen_md5($TOKEN, $data, $random)}", "authorization": "${gen_md5($TOKEN, $data, $random)}",
"TOKEN": "debugtalk" "TOKEN": "debugtalk"
} }
functions = {
"gen_random_string": gen_random_string,
"gen_md5": gen_md5
}
variables = parser.prepare_lazy_data(variables, functions, variables.keys())
variables = parser.parse_variables_mapping(variables)
self.context.init_test_variables(variables) self.context.init_test_variables(variables)
request = { request = {
@@ -90,7 +107,12 @@ class TestContext(ApiServerUnittest):
}, },
"data": "$data" "data": "$data"
} }
parsed_request = self.context.eval_content(request) prepared_request = parser.prepare_lazy_data(
request,
functions,
{"authorization", "random", "SECRET_KEY", "data"}
)
parsed_request = self.context.eval_content(prepared_request)
self.assertIn("authorization", parsed_request["headers"]) self.assertIn("authorization", parsed_request["headers"])
self.assertEqual(len(parsed_request["headers"]["authorization"]), 32) self.assertEqual(len(parsed_request["headers"]["authorization"]), 32)
self.assertIn("random", parsed_request["headers"]) self.assertIn("random", parsed_request["headers"])
@@ -123,6 +145,7 @@ class TestContext(ApiServerUnittest):
{"check": "$resp_status_code", "comparator": "eq", "expect": 201}, {"check": "$resp_status_code", "comparator": "eq", "expect": 201},
{"check": "$resp_body_success", "comparator": "eq", "expect": True} {"check": "$resp_body_success", "comparator": "eq", "expect": True}
] ]
validators = parser.prepare_lazy_data(validators, {}, {"resp_status_code", "resp_body_success"})
variables = { variables = {
"resp_status_code": 200, "resp_status_code": 200,
"resp_body_success": True "resp_body_success": True
@@ -139,6 +162,12 @@ class TestContext(ApiServerUnittest):
{"check": "$resp_body_success", "comparator": "eq", "expect": True}, {"check": "$resp_body_success", "comparator": "eq", "expect": True},
{"check": "${is_status_code_200($resp_status_code)}", "comparator": "eq", "expect": False} {"check": "${is_status_code_200($resp_status_code)}", "comparator": "eq", "expect": False}
] ]
from tests.debugtalk import is_status_code_200
functions = {
"is_status_code_200": is_status_code_200
}
validators = parser.prepare_lazy_data(
validators, functions, {"resp_status_code", "resp_body_success"})
variables = [ variables = [
{"resp_status_code": 201}, {"resp_status_code": 201},
{"resp_body_success": True} {"resp_body_success": True}
@@ -159,6 +188,7 @@ class TestContext(ApiServerUnittest):
{"eq": ["$resp_status_code", 201]}, {"eq": ["$resp_status_code", 201]},
{"check": "$resp_status_code", "comparator": "eq", "expect": 201} {"check": "$resp_status_code", "comparator": "eq", "expect": 201}
] ]
validators = parser.prepare_lazy_data(validators, {}, {"resp_status_code"})
variables = [] variables = []
self.context.init_test_variables(variables) self.context.init_test_variables(variables)

View File

@@ -348,14 +348,14 @@ class TestSuiteLoader(unittest.TestCase):
tests_mapping = loader.load_tests(testcase_file_path) tests_mapping = loader.load_tests(testcase_file_path)
testcases = tests_mapping["testcases"] testcases = tests_mapping["testcases"]
self.assertIsInstance(testcases, list) self.assertIsInstance(testcases, list)
self.assertEqual(testcases[0]["config"]["name"], '123$var_a') self.assertEqual(testcases[0]["config"]["name"], '123t$var_a')
self.assertIn( self.assertIn(
"sum_two", "sum_two",
tests_mapping["project_mapping"]["functions"] tests_mapping["project_mapping"]["functions"]
) )
self.assertEqual( self.assertEqual(
testcases[0]["config"]["variables"]["var_c"], testcases[0]["config"]["variables"]["var_c"],
"${sum_two(1, 2)}" "${sum_two($var_a, $var_b)}"
) )
self.assertEqual( self.assertEqual(
testcases[0]["config"]["variables"]["PROJECT_KEY"], testcases[0]["config"]["variables"]["PROJECT_KEY"],

View File

@@ -1,11 +1,13 @@
import os import os
import re
import time import time
import unittest import unittest
from httprunner import exceptions, loader, parser from httprunner import exceptions, loader, parser
from tests.debugtalk import gen_random_string, sum_two
class TestParser(unittest.TestCase): class TestParserBasic(unittest.TestCase):
def test_parse_string_value(self): def test_parse_string_value(self):
self.assertEqual(parser.parse_string_value("123"), 123) self.assertEqual(parser.parse_string_value("123"), 123)
@@ -14,92 +16,92 @@ class TestParser(unittest.TestCase):
self.assertEqual(parser.parse_string_value("$var"), "$var") self.assertEqual(parser.parse_string_value("$var"), "$var")
self.assertEqual(parser.parse_string_value("${func}"), "${func}") self.assertEqual(parser.parse_string_value("${func}"), "${func}")
def test_extract_variables(self): def test_regex_findall_variables(self):
self.assertEqual( self.assertEqual(
parser.extract_variables("$var"), parser.regex_findall_variables("$var"),
["var"] ["var"]
) )
self.assertEqual( self.assertEqual(
parser.extract_variables("$var123"), parser.regex_findall_variables("$var123"),
["var123"] ["var123"]
) )
self.assertEqual( self.assertEqual(
parser.extract_variables("$var_name"), parser.regex_findall_variables("$var_name"),
["var_name"] ["var_name"]
) )
self.assertEqual( self.assertEqual(
parser.extract_variables("var"), parser.regex_findall_variables("var"),
[] []
) )
self.assertEqual( self.assertEqual(
parser.extract_variables("a$var"), parser.regex_findall_variables("a$var"),
["var"] ["var"]
) )
self.assertEqual( self.assertEqual(
parser.extract_variables("$v ar"), parser.regex_findall_variables("$v ar"),
["v"] ["v"]
) )
self.assertEqual( self.assertEqual(
parser.extract_variables(" "), parser.regex_findall_variables(" "),
[] []
) )
self.assertEqual( self.assertEqual(
parser.extract_variables("$abc*"), parser.regex_findall_variables("$abc*"),
["abc"] ["abc"]
) )
self.assertEqual( self.assertEqual(
parser.extract_variables("${func()}"), parser.regex_findall_variables("${func()}"),
[] []
) )
self.assertEqual( self.assertEqual(
parser.extract_variables("${func(1,2)}"), parser.regex_findall_variables("${func(1,2)}"),
[] []
) )
self.assertEqual( self.assertEqual(
parser.extract_variables("${gen_md5($TOKEN, $data, $random)}"), parser.regex_findall_variables("${gen_md5($TOKEN, $data, $random)}"),
["TOKEN", "data", "random"] ["TOKEN", "data", "random"]
) )
def test_parse_function(self): def test_parse_function_params(self):
self.assertEqual( self.assertEqual(
parser.parse_function("func()"), parser.parse_function_params(""),
{'func_name': 'func', 'args': [], 'kwargs': {}} {'args': [], 'kwargs': {}}
) )
self.assertEqual( self.assertEqual(
parser.parse_function("func(5)"), parser.parse_function_params("5"),
{'func_name': 'func', 'args': [5], 'kwargs': {}} {'args': [5], 'kwargs': {}}
) )
self.assertEqual( self.assertEqual(
parser.parse_function("func(1, 2)"), parser.parse_function_params("1, 2"),
{'func_name': 'func', 'args': [1, 2], 'kwargs': {}} {'args': [1, 2], 'kwargs': {}}
) )
self.assertEqual( self.assertEqual(
parser.parse_function("func(a=1, b=2)"), parser.parse_function_params("a=1, b=2"),
{'func_name': 'func', 'args': [], 'kwargs': {'a': 1, 'b': 2}} {'args': [], 'kwargs': {'a': 1, 'b': 2}}
) )
self.assertEqual( self.assertEqual(
parser.parse_function("func(a= 1, b =2)"), parser.parse_function_params("a= 1, b =2"),
{'func_name': 'func', 'args': [], 'kwargs': {'a': 1, 'b': 2}} {'args': [], 'kwargs': {'a': 1, 'b': 2}}
) )
self.assertEqual( self.assertEqual(
parser.parse_function("func(1, 2, a=3, b=4)"), parser.parse_function_params("1, 2, a=3, b=4"),
{'func_name': 'func', 'args': [1, 2], 'kwargs': {'a': 3, 'b': 4}} {'args': [1, 2], 'kwargs': {'a': 3, 'b': 4}}
) )
self.assertEqual( self.assertEqual(
parser.parse_function("func($request, 123)"), parser.parse_function_params("$request, 123"),
{'func_name': 'func', 'args': ["$request", 123], 'kwargs': {}} {'args': ["$request", 123], 'kwargs': {}}
) )
self.assertEqual( self.assertEqual(
parser.parse_function("func( )"), parser.parse_function_params(" "),
{'func_name': 'func', 'args': [], 'kwargs': {}} {'args': [], 'kwargs': {}}
) )
self.assertEqual( self.assertEqual(
parser.parse_function("func(hello world, a=3, b=4)"), parser.parse_function_params("hello world, a=3, b=4"),
{'func_name': 'func', 'args': ["hello world"], 'kwargs': {'a': 3, 'b': 4}} {'args': ["hello world"], 'kwargs': {'a': 3, 'b': 4}}
) )
self.assertEqual( self.assertEqual(
parser.parse_function("func($request, 12 3)"), parser.parse_function_params("$request, 12 3"),
{'func_name': 'func', 'args': ["$request", '12 3'], 'kwargs': {}} {'args': ["$request", '12 3'], 'kwargs': {}}
) )
def test_parse_validator(self): def test_parse_validator(self):
@@ -115,38 +117,82 @@ class TestParser(unittest.TestCase):
{"check": "status_code", "comparator": "eq", "expect": 201} {"check": "status_code", "comparator": "eq", "expect": 201}
) )
def test_extract_variables(self):
prepared_content = parser.prepare_lazy_data("123$a", {}, {"a"})
self.assertEqual(
parser.extract_variables(prepared_content),
{"a"}
)
prepared_content = parser.prepare_lazy_data("$a$b", {}, {"a", "b"})
self.assertEqual(
parser.extract_variables(prepared_content),
{"a", "b"}
)
prepared_content = parser.prepare_lazy_data(["$a$b", "$c", "d"], {}, {"a", "b", "c", "d"})
self.assertEqual(
parser.extract_variables(prepared_content),
{"a", "b", "c"}
)
prepared_content = parser.prepare_lazy_data(
{"a": 1, "b": {"c": "$d", "e": 3}},
{},
{"d"}
)
self.assertEqual(
parser.extract_variables(prepared_content),
{"d"}
)
prepared_content = parser.prepare_lazy_data(
{"a": ["$b"], "b": {"c": "$d", "e": 3}},
{},
{"b", "d"}
)
self.assertEqual(
parser.extract_variables(prepared_content),
{"b", "d"}
)
prepared_content = parser.prepare_lazy_data(
["$a$b", "$c", {"c": "$d"}],
{},
{"a", "b", "c", "d"}
)
self.assertEqual(
parser.extract_variables(prepared_content),
{"a", "b", "c", "d"}
)
def test_extract_functions(self): def test_extract_functions(self):
self.assertEqual( self.assertEqual(
parser.extract_functions("${func()}"), parser.regex_findall_functions("${func()}"),
["func()"] [('func', '')]
) )
self.assertEqual( self.assertEqual(
parser.extract_functions("${func(5)}"), parser.regex_findall_functions("${func(5)}"),
["func(5)"] [('func', '5')]
) )
self.assertEqual( self.assertEqual(
parser.extract_functions("${func(a=1, b=2)}"), parser.regex_findall_functions("${func(a=1, b=2)}"),
["func(a=1, b=2)"] [('func', 'a=1, b=2')]
) )
self.assertEqual( self.assertEqual(
parser.extract_functions("${func(1, $b, c=$x, d=4)}"), parser.regex_findall_functions("${func(1, $b, c=$x, d=4)}"),
["func(1, $b, c=$x, d=4)"] [('func', '1, $b, c=$x, d=4')]
) )
self.assertEqual( self.assertEqual(
parser.extract_functions("/api/1000?_t=${get_timestamp()}"), parser.regex_findall_functions("/api/1000?_t=${get_timestamp()}"),
["get_timestamp()"] [('get_timestamp', '')]
) )
self.assertEqual( self.assertEqual(
parser.extract_functions("/api/${add(1, 2)}"), parser.regex_findall_functions("/api/${add(1, 2)}"),
["add(1, 2)"] [('add', '1, 2')]
) )
self.assertEqual( self.assertEqual(
parser.extract_functions("/api/${add(1, 2)}?_t=${get_timestamp()}"), parser.regex_findall_functions("/api/${add(1, 2)}?_t=${get_timestamp()}"),
["add(1, 2)", "get_timestamp()"] [('add', '1, 2'), ('get_timestamp', '')]
) )
self.assertEqual( self.assertEqual(
parser.extract_functions("abc${func(1, 2, a=3, b=4)}def"), parser.regex_findall_functions("abc${func(1, 2, a=3, b=4)}def"),
["func(1, 2, a=3, b=4)"] [('func', '1, 2, a=3, b=4')]
) )
def test_parse_data(self): def test_parse_data(self):
@@ -172,7 +218,7 @@ class TestParser(unittest.TestCase):
functions_mapping = { functions_mapping = {
"add_one": lambda x: x + 1 "add_one": lambda x: x + 1
} }
result = parser.parse_data(content, variables_mapping, functions_mapping) result = parser.eval_lazy_data(content, variables_mapping, functions_mapping)
self.assertEqual("/api/users/1000", result["request"]["url"]) self.assertEqual("/api/users/1000", result["request"]["url"])
self.assertEqual("abc123", result["request"]["headers"]["token"]) self.assertEqual("abc123", result["request"]["headers"]["token"])
self.assertEqual("POST", result["request"]["method"]) self.assertEqual("POST", result["request"]["method"])
@@ -182,7 +228,7 @@ class TestParser(unittest.TestCase):
self.assertEqual("", result["request"]["data"]["empty_str"]) self.assertEqual("", result["request"]["data"]["empty_str"])
self.assertEqual("abc4def", result["request"]["data"]["value"]) self.assertEqual("abc4def", result["request"]["data"]["value"])
def test_parse_data_variables(self): def test_eval_lazy_data(self):
variables_mapping = { variables_mapping = {
"var_1": "abc", "var_1": "abc",
"var_2": "def", "var_2": "def",
@@ -192,66 +238,150 @@ class TestParser(unittest.TestCase):
"var_6": None "var_6": None
} }
self.assertEqual( self.assertEqual(
parser.parse_data("$var_1", variables_mapping), parser.eval_lazy_data("$var_1", variables_mapping=variables_mapping),
"abc" "abc"
) )
self.assertEqual( self.assertEqual(
parser.parse_data("var_1", variables_mapping), parser.eval_lazy_data("var_1", variables_mapping=variables_mapping),
"var_1" "var_1"
) )
self.assertEqual( self.assertEqual(
parser.parse_data("$var_1#XYZ", variables_mapping), parser.eval_lazy_data("$var_1#XYZ", variables_mapping=variables_mapping),
"abc#XYZ" "abc#XYZ"
) )
self.assertEqual( self.assertEqual(
parser.parse_data("/$var_1/$var_2/var3", variables_mapping), parser.eval_lazy_data("/$var_1/$var_2/var3", variables_mapping=variables_mapping),
"/abc/def/var3" "/abc/def/var3"
) )
self.assertEqual( self.assertEqual(
parser.parse_data("/$var_1/$var_2/$var_1", variables_mapping), parser.eval_lazy_data("/$var_1/$var_2/$var_1", variables_mapping=variables_mapping),
"/abc/def/abc" "/abc/def/abc"
) )
self.assertEqual( self.assertEqual(
parser.parse_string_variables("${func($var_1, $var_2, xyz)}", variables_mapping, {}), parser.eval_lazy_data("$var_3", variables_mapping=variables_mapping),
"${func(abc, def, xyz)}"
)
self.assertEqual(
parser.parse_data("$var_3", variables_mapping),
123 123
) )
self.assertEqual( self.assertEqual(
parser.parse_data("$var_4", variables_mapping), parser.eval_lazy_data("$var_4", variables_mapping=variables_mapping),
{"a": 1} {"a": 1}
) )
self.assertEqual( self.assertEqual(
parser.parse_data("$var_5", variables_mapping), parser.eval_lazy_data("$var_5", variables_mapping=variables_mapping),
True True
) )
self.assertEqual( self.assertEqual(
parser.parse_data("abc$var_5", variables_mapping), parser.eval_lazy_data("abc$var_5", variables_mapping=variables_mapping),
"abcTrue" "abcTrue"
) )
self.assertEqual( self.assertEqual(
parser.parse_data("abc$var_4", variables_mapping), parser.eval_lazy_data("abc$var_4", variables_mapping=variables_mapping),
"abc{'a': 1}" "abc{'a': 1}"
) )
self.assertEqual( self.assertEqual(
parser.parse_data("$var_6", variables_mapping), parser.eval_lazy_data("$var_6", variables_mapping=variables_mapping),
None None
) )
with self.assertRaises(exceptions.VariableNotFound): with self.assertRaises(exceptions.VariableNotFound):
parser.parse_data("/api/$SECRET_KEY", variables_mapping) parser.eval_lazy_data("/api/$SECRET_KEY", variables_mapping=variables_mapping)
self.assertEqual( self.assertEqual(
parser.parse_data(["$var_1", "$var_2"], variables_mapping), parser.eval_lazy_data(["$var_1", "$var_2"], variables_mapping=variables_mapping),
["abc", "def"] ["abc", "def"]
) )
self.assertEqual( self.assertEqual(
parser.parse_data({"$var_1": "$var_2"}, variables_mapping), parser.eval_lazy_data({"$var_1": "$var_2"}, variables_mapping=variables_mapping),
{"abc": "def"} {"abc": "def"}
) )
def test_lazy_string(self):
variables_mapping = {
"var_1": "abc",
"var_2": "def",
"var_3": 123,
"var_4": {"a": 1},
"var_5": True,
"var_6": None
}
check_variables_set = variables_mapping.keys()
functions_mapping = {
"func1": lambda x,y: str(x) + str(y)
}
var = parser.LazyString("ABC$var_1", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}")
self.assertEqual(var._args, ["var_1"])
self.assertEqual(var.to_value(variables_mapping), "ABCabc")
var = parser.LazyString("ABC$var_1$var_3", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}{}")
self.assertEqual(var._args, ["var_1", "var_3"])
self.assertEqual(var.to_value(variables_mapping), "ABCabc123")
var = parser.LazyString("ABC$var_1/$var_3", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}/{}")
self.assertEqual(var._args, ["var_1", "var_3"])
self.assertEqual(var.to_value(variables_mapping), "ABCabc/123")
var = parser.LazyString("ABC$var_1/", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}/")
self.assertEqual(var._args, ["var_1"])
self.assertEqual(var.to_value(variables_mapping), "ABCabc/")
var = parser.LazyString("ABC$var_1$", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}$")
self.assertEqual(var._args, ["var_1"])
self.assertEqual(var.to_value(variables_mapping), "ABCabc$")
var = parser.LazyString("ABC$var_1{", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}{")
self.assertEqual(var._args, ["var_1"])
# self.assertEqual(var.to_value(variables_mapping), "ABCabc{")
var = parser.LazyString("ABC$$var_1{", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC${}{")
self.assertEqual(var._args, ["var_1"])
var = parser.LazyString("ABC$var_1${", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}${")
self.assertEqual(var._args, ["var_1"])
var = parser.LazyString("ABC$var_1${a", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}${a")
self.assertEqual(var._args, ["var_1"])
var = parser.LazyString("ABC$var_1/$var_2/$var_1", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}/{}/{}")
self.assertEqual(var._args, ["var_1", "var_2", "var_1"])
self.assertEqual(var.to_value(variables_mapping), "ABCabc/def/abc")
var = parser.LazyString("func1($var_1, $var_3)", functions_mapping, check_variables_set)
self.assertEqual(var._string, "func1({}, {})")
self.assertEqual(var._args, ["var_1", "var_3"])
self.assertEqual(var.to_value(variables_mapping), "func1(abc, 123)")
var = parser.LazyString("${func1($var_1, $var_3)}", functions_mapping, check_variables_set)
self.assertEqual(var._string, "{}")
self.assertIsInstance(var._args[0], parser.LazyFunction)
self.assertEqual(var.to_value(variables_mapping), "abc123")
var = parser.LazyString("ABC${func1($var_1, $var_3)}DE", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}DE")
self.assertIsInstance(var._args[0], parser.LazyFunction)
self.assertEqual(var.to_value(variables_mapping), "ABCabc123DE")
var = parser.LazyString("ABC${func1($var_1, $var_3)}$var_5", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}{}")
self.assertEqual(var.to_value(variables_mapping), "ABCabc123True")
var = parser.LazyString("ABC${func1($var_1, $var_3)}DE$var_4", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}DE{}")
self.assertEqual(var.to_value(variables_mapping), "ABCabc123DE{'a': 1}")
var = parser.LazyString("ABC$var_5${func1($var_1, $var_3)}", functions_mapping, check_variables_set)
self.assertEqual(var._string, "ABC{}{}")
self.assertEqual(var.to_value(variables_mapping), "ABCTrueabc123")
def test_parse_data_multiple_identical_variables(self): def test_parse_data_multiple_identical_variables(self):
variables_mapping = { variables_mapping = {
"userid": 100, "userid": 100,
@@ -259,7 +389,7 @@ class TestParser(unittest.TestCase):
} }
content = "/users/$userid/training/$data?userId=$userid&data=$data" content = "/users/$userid/training/$data?userId=$userid&data=$data"
self.assertEqual( self.assertEqual(
parser.parse_data(content, variables_mapping), parser.eval_lazy_data(content, variables_mapping=variables_mapping),
"/users/100/training/1498?userId=100&data=1498" "/users/100/training/1498?userId=100&data=1498"
) )
@@ -270,36 +400,35 @@ class TestParser(unittest.TestCase):
} }
content = "/users/$user/$userid/$data?userId=$userid&data=$data" content = "/users/$user/$userid/$data?userId=$userid&data=$data"
self.assertEqual( self.assertEqual(
parser.parse_data(content, variables_mapping), parser.eval_lazy_data(content, variables_mapping=variables_mapping),
"/users/100/1000/1498?userId=1000&data=1498" "/users/100/1000/1498?userId=1000&data=1498"
) )
def test_parse_data_functions(self): def test_parse_data_functions(self):
import random, string import random, string
functions_mapping = { functions_mapping = {
"gen_random_string": lambda str_len: ''.join(random.choice(string.ascii_letters + string.digits) \ "gen_random_string": gen_random_string
for _ in range(str_len))
} }
result = parser.parse_data("${gen_random_string(5)}", functions_mapping=functions_mapping) result = parser.eval_lazy_data("${gen_random_string(5)}", functions_mapping=functions_mapping)
self.assertEqual(len(result), 5) self.assertEqual(len(result), 5)
add_two_nums = lambda a, b=1: a + b add_two_nums = lambda a, b=1: a + b
functions_mapping["add_two_nums"] = add_two_nums functions_mapping["add_two_nums"] = add_two_nums
self.assertEqual( self.assertEqual(
parser.parse_data("${add_two_nums(1)}", functions_mapping=functions_mapping), parser.eval_lazy_data("${add_two_nums(1)}", functions_mapping=functions_mapping),
2 2
) )
self.assertEqual( self.assertEqual(
parser.parse_data("${add_two_nums(1, 2)}", functions_mapping=functions_mapping), parser.eval_lazy_data("${add_two_nums(1, 2)}", functions_mapping=functions_mapping),
3 3
) )
self.assertEqual( self.assertEqual(
parser.parse_data("/api/${add_two_nums(1, 2)}", functions_mapping=functions_mapping), parser.eval_lazy_data("/api/${add_two_nums(1, 2)}", functions_mapping=functions_mapping),
"/api/3" "/api/3"
) )
with self.assertRaises(exceptions.FunctionNotFound): with self.assertRaises(exceptions.FunctionNotFound):
parser.parse_data("/api/${gen_md5(abc)}") parser.eval_lazy_data("/api/${gen_md5(abc)}", functions_mapping=functions_mapping)
def test_parse_data_testcase(self): def test_parse_data_testcase(self):
variables = { variables = {
@@ -323,7 +452,11 @@ class TestParser(unittest.TestCase):
}, },
"body": "$data" "body": "$data"
} }
parsed_testcase = parser.parse_data(testcase_template, variables, functions) parsed_testcase = parser.eval_lazy_data(
testcase_template,
variables_mapping=variables,
functions_mapping=functions
)
self.assertEqual( self.assertEqual(
parsed_testcase["url"], parsed_testcase["url"],
"http://127.0.0.1:5000/api/users/1000/3" "http://127.0.0.1:5000/api/users/1000/3"
@@ -345,13 +478,123 @@ class TestParser(unittest.TestCase):
3 3
) )
def test_parse_variables_mapping(self):
variables = {
"varA": "123$varB",
"varB": "456$varC",
"varC": "${sum_two($a, $b)}",
"a": 1,
"b": 2
}
functions = {
"sum_two": sum_two
}
prepared_variables = parser.prepare_lazy_data(variables, functions, variables.keys())
parsed_variables = parser.parse_variables_mapping(prepared_variables)
self.assertEqual(parsed_variables["varA"], "1234563")
self.assertEqual(parsed_variables["varB"], "4563")
self.assertEqual(parsed_variables["varC"], 3)
def test_parse_variables_mapping_fix_duplicate_function_call(self):
# fix duplicate function calling
variables = {
"varA": "$varB",
"varB": "${gen_random_string(5)}"
}
functions = {
"gen_random_string": gen_random_string
}
prepared_variables = parser.prepare_lazy_data(variables, functions, variables.keys())
parsed_variables = parser.parse_variables_mapping(prepared_variables)
self.assertEqual(parsed_variables["varA"], parsed_variables["varB"])
def test_parse_variables_mapping_not_found(self):
variables = {
"varA": "123$varB",
"varB": "456$varC",
"varC": "${sum_two($a, $b)}",
"b": 2
}
functions = {
"sum_two": sum_two
}
with self.assertRaises(exceptions.VariableNotFound):
parser.prepare_lazy_data(variables, functions, variables.keys())
def test_parse_variables_mapping_ref_self(self):
variables = {
"varC": "${sum_two($a, $b)}",
"a": 1,
"b": 2,
"token": "$token"
}
functions = {
"sum_two": sum_two
}
prepared_variables = parser.prepare_lazy_data(variables, functions, variables.keys())
with self.assertRaises(exceptions.VariableNotFound):
parser.parse_variables_mapping(prepared_variables)
def test_parse_variables_mapping_2(self):
variables = {
"host2": "https://httprunner.org",
"num3": "${sum_two($num2, 4)}",
"num2": "${sum_two($num1, 3)}",
"num1": "${sum_two(1, 2)}"
}
functions = {
"sum_two": sum_two
}
prepared_variables = parser.prepare_lazy_data(variables, functions, variables.keys())
parsed_testcase = parser.parse_variables_mapping(prepared_variables)
self.assertEqual(parsed_testcase["num3"], 10)
self.assertEqual(parsed_testcase["num2"], 6)
self.assertEqual(parsed_testcase["num1"], 3)
def test_prepare_lazy_data(self):
variables = {
"host": "https://httprunner.org",
"num4": "${sum_two($num0, 5)}",
"num3": "${sum_two($num2, 4)}",
"num2": "${sum_two($num1, 3)}",
"num1": "${sum_two(1, 2)}",
"num0": 0
}
functions = {
"sum_two": sum_two
}
parser.prepare_lazy_data(
variables,
functions,
variables.keys()
)
def test_prepare_lazy_data_not_found(self):
variables = {
"host": "https://httprunner.org",
"num4": "${sum_two($num0, 5)}",
"num3": "${sum_two($num2, 4)}",
"num2": "${sum_two($num1, 3)}",
"num1": "${sum_two(1, 2)}"
}
functions = {
"sum_two": sum_two
}
with self.assertRaises(exceptions.VariableNotFound):
parser.prepare_lazy_data(
variables,
functions,
variables.keys()
)
class TestParser(unittest.TestCase):
def test_parse_parameters_raw_list(self): def test_parse_parameters_raw_list(self):
parameters = [ parameters = [
{"user_agent": ["iOS/10.1", "iOS/10.2", "iOS/10.3"]}, {"user_agent": ["iOS/10.1", "iOS/10.2", "iOS/10.3"]},
{"username-password": [("user1", "111111"), ["test2", "222222"]]} {"username-password": [("user1", "111111"), ["test2", "222222"]]}
] ]
variables_mapping = {}
functions_mapping = {}
cartesian_product_parameters = parser.parse_parameters(parameters) cartesian_product_parameters = parser.parse_parameters(parameters)
self.assertEqual( self.assertEqual(
len(cartesian_product_parameters), len(cartesian_product_parameters),
@@ -429,7 +672,7 @@ class TestParser(unittest.TestCase):
testcases = tests_mapping["testcases"] testcases = tests_mapping["testcases"]
self.assertEqual( self.assertEqual(
testcases[0]["config"]["variables"]["var_c"], testcases[0]["config"]["variables"]["var_c"],
"${sum_two(1, 2)}" "${sum_two($var_a, $var_b)}"
) )
self.assertEqual( self.assertEqual(
testcases[0]["config"]["variables"]["PROJECT_KEY"], testcases[0]["config"]["variables"]["PROJECT_KEY"],
@@ -439,10 +682,9 @@ class TestParser(unittest.TestCase):
parsed_testcases = parsed_tests_mapping["testcases"] parsed_testcases = parsed_tests_mapping["testcases"]
self.assertIsInstance(parsed_testcases, list) self.assertIsInstance(parsed_testcases, list)
test_dict1 = parsed_testcases[0]["teststeps"][0] test_dict1 = parsed_testcases[0]["teststeps"][0]
self.assertEqual(test_dict1["variables"]["var_c"], 3) self.assertEqual(test_dict1["variables"]["var_c"].raw_string, "${sum_two($var_a, $var_b)}")
self.assertEqual(test_dict1["variables"]["PROJECT_KEY"], "ABCDEFGH") self.assertEqual(test_dict1["variables"]["PROJECT_KEY"].raw_string, "${ENV(PROJECT_KEY)}")
self.assertEqual(test_dict1["variables"]["var_d"], test_dict1["variables"]["var_e"]) self.assertIsInstance(parsed_testcases[0]["config"]["name"], parser.LazyString)
self.assertEqual(parsed_testcases[0]["config"]["name"], '1230')
def test_parse_tests_override_variables(self): def test_parse_tests_override_variables(self):
tests_mapping = { tests_mapping = {
@@ -471,7 +713,7 @@ class TestParser(unittest.TestCase):
parsed_tests_mapping = parser.parse_tests(tests_mapping) parsed_tests_mapping = parser.parse_tests(tests_mapping)
test_dict1_variables = parsed_tests_mapping["testcases"][0]["teststeps"][0]["variables"] test_dict1_variables = parsed_tests_mapping["testcases"][0]["teststeps"][0]["variables"]
self.assertEqual(test_dict1_variables["creator"], "user_test_001") self.assertEqual(test_dict1_variables["creator"], "user_test_001")
self.assertEqual(test_dict1_variables["username"], "user_test_001") self.assertEqual(test_dict1_variables["username"].raw_string, "$creator")
def test_parse_tests_base_url_priority(self): def test_parse_tests_base_url_priority(self):
""" base_url & verify: priority test_dict > config """ base_url & verify: priority test_dict > config
@@ -499,7 +741,7 @@ class TestParser(unittest.TestCase):
} }
parsed_tests_mapping = parser.parse_tests(tests_mapping) parsed_tests_mapping = parser.parse_tests(tests_mapping)
test_dict = parsed_tests_mapping["testcases"][0]["teststeps"][0] test_dict = parsed_tests_mapping["testcases"][0]["teststeps"][0]
self.assertEqual(test_dict["request"]["url"], "https://httprunner.org/api1") self.assertEqual(test_dict["request"]["url"], "/api1")
self.assertEqual(test_dict["request"]["verify"], True) self.assertEqual(test_dict["request"]["verify"], True)
def test_parse_tests_base_url_path_with_variable(self): def test_parse_tests_base_url_path_with_variable(self):
@@ -527,7 +769,9 @@ class TestParser(unittest.TestCase):
} }
parsed_tests_mapping = parser.parse_tests(tests_mapping) parsed_tests_mapping = parser.parse_tests(tests_mapping)
test_dict = parsed_tests_mapping["testcases"][0]["teststeps"][0] test_dict = parsed_tests_mapping["testcases"][0]["teststeps"][0]
self.assertEqual(test_dict["request"]["url"], "https://httprunner.org/api1") self.assertEqual(test_dict["variables"]["host2"], "https://httprunner.org")
parsed_test_dict = parser.parse_lazy_data(test_dict, test_dict["variables"])
self.assertEqual(parsed_test_dict["request"]["url"], "https://httprunner.org/api1")
def test_parse_tests_base_url_test_dict(self): def test_parse_tests_base_url_test_dict(self):
tests_mapping = { tests_mapping = {
@@ -555,52 +799,10 @@ class TestParser(unittest.TestCase):
} }
parsed_tests_mapping = parser.parse_tests(tests_mapping) parsed_tests_mapping = parser.parse_tests(tests_mapping)
test_dict = parsed_tests_mapping["testcases"][0]["teststeps"][0] test_dict = parsed_tests_mapping["testcases"][0]["teststeps"][0]
self.assertEqual(test_dict["request"]["url"], "https://httprunner.org/api1") parsed_test_dict = parser.parse_lazy_data(test_dict, test_dict["variables"])
self.assertEqual(parsed_test_dict["base_url"], "https://httprunner.org")
def test_parse_data_with_variables(self):
variables = {
"host2": "https://httprunner.org",
"num3": "${sum_two($num2, 4)}",
"num2": "${sum_two($num1, 3)}",
"num1": "${sum_two(1, 2)}"
}
from tests.debugtalk import sum_two
functions = {
"sum_two": sum_two
}
parsed_testcase = parser.parse_data(variables, variables, functions)
self.assertEqual(parsed_testcase["num3"], 10)
self.assertEqual(parsed_testcase["num2"], 6)
self.assertEqual(parsed_testcase["num1"], 3)
def test_parse_data_with_variables_not_found(self):
variables = {
"host": "https://httprunner.org",
"num4": "${sum_two($num0, 5)}",
"num3": "${sum_two($num2, 4)}",
"num2": "${sum_two($num1, 3)}",
"num1": "${sum_two(1, 2)}"
}
from tests.debugtalk import sum_two
functions = {
"sum_two": sum_two
}
with self.assertRaises(exceptions.VariableNotFound):
parser.parse_data(variables, variables, functions)
parsed_testcase = parser.parse_data(
variables,
variables,
functions,
raise_if_variable_not_found=False
)
self.assertEqual(parsed_testcase["num3"], 10)
self.assertEqual(parsed_testcase["num2"], 6)
self.assertEqual(parsed_testcase["num1"], 3)
self.assertEqual(parsed_testcase["num4"], "${sum_two($num0, 5)}")
def test_parse_tests_variable_with_function(self): def test_parse_tests_variable_with_function(self):
from tests.debugtalk import sum_two, gen_random_string
tests_mapping = { tests_mapping = {
"project_mapping": { "project_mapping": {
"functions": { "functions": {
@@ -642,16 +844,18 @@ class TestParser(unittest.TestCase):
} }
parsed_tests_mapping = parser.parse_tests(tests_mapping) parsed_tests_mapping = parser.parse_tests(tests_mapping)
test_dict = parsed_tests_mapping["testcases"][0]["teststeps"][0] test_dict = parsed_tests_mapping["testcases"][0]["teststeps"][0]
self.assertEqual(test_dict["variables"]["num3"], 10) variables = parser.parse_variables_mapping(test_dict["variables"])
self.assertEqual(test_dict["variables"]["num2"], 6) self.assertEqual(variables["num3"], 10)
self.assertEqual(test_dict["variables"]["str1"], test_dict["variables"]["str2"]) self.assertEqual(variables["num2"], 6)
parsed_test_dict = parser.parse_lazy_data(test_dict, variables)
self.assertEqual(parsed_test_dict["base_url"], "https://httprunner.org")
self.assertEqual( self.assertEqual(
test_dict["request"]["url"], parsed_test_dict["request"]["url"],
"https://httprunner.org/api1/?num1=3&num2=6&num3=10" "/api1/?num1=3&num2=6&num3=10"
) )
self.assertEqual(variables["str1"], variables["str2"])
def test_parse_tests_variable_not_found(self): def test_parse_tests_variable_not_found(self):
from tests.debugtalk import sum_two
tests_mapping = { tests_mapping = {
"project_mapping": { "project_mapping": {
"functions": { "functions": {
@@ -687,15 +891,8 @@ class TestParser(unittest.TestCase):
} }
] ]
} }
parsed_tests_mapping = parser.parse_tests(tests_mapping) with self.assertRaises(exceptions.VariableNotFound):
test_dict = parsed_tests_mapping["testcases"][0]["teststeps"][0] parser.parse_tests(tests_mapping)
self.assertEqual(test_dict["variables"]["num3"], 10)
self.assertEqual(test_dict["variables"]["num2"], 6)
self.assertEqual(test_dict["variables"]["num4"], "${sum_two($num0, 5)}")
self.assertEqual(
test_dict["request"]["url"],
"https://httprunner.org/api1/?num1=3&num2=6&num3=10&num4=${sum_two($num0, 5)}"
)
def test_parse_tests_base_url_teststep_empty(self): def test_parse_tests_base_url_teststep_empty(self):
""" base_url & verify: priority test_dict > config """ base_url & verify: priority test_dict > config
@@ -723,7 +920,7 @@ class TestParser(unittest.TestCase):
} }
parsed_tests_mapping = parser.parse_tests(tests_mapping) parsed_tests_mapping = parser.parse_tests(tests_mapping)
test_dict = parsed_tests_mapping["testcases"][0]["teststeps"][0] test_dict = parsed_tests_mapping["testcases"][0]["teststeps"][0]
self.assertEqual(test_dict["request"]["url"], "https://debugtalk.com/api1") self.assertEqual(str(test_dict["base_url"]), 'LazyString($host)')
self.assertEqual(test_dict["request"]["verify"], True) self.assertEqual(test_dict["request"]["verify"], True)
def test_parse_tests_verify_config_set(self): def test_parse_tests_verify_config_set(self):
@@ -839,7 +1036,7 @@ class TestParser(unittest.TestCase):
{"PROJECT_KEY": "${ENV(PROJECT_KEY)}"} {"PROJECT_KEY": "${ENV(PROJECT_KEY)}"}
] ]
} }
result = parser.parse_data(content) result = parser.eval_lazy_data(content)
content = { content = {
"variables": [ "variables": [
@@ -847,7 +1044,7 @@ class TestParser(unittest.TestCase):
] ]
} }
with self.assertRaises(exceptions.ParamsError): with self.assertRaises(exceptions.ParamsError):
parser.parse_data(content) parser.eval_lazy_data(content)
content = { content = {
"variables": [ "variables": [
@@ -855,7 +1052,7 @@ class TestParser(unittest.TestCase):
] ]
} }
with self.assertRaises(exceptions.ParamsError): with self.assertRaises(exceptions.ParamsError):
parser.parse_data(content) parser.eval_lazy_data(content)
def test_extend_with_api(self): def test_extend_with_api(self):
loader.load_project_tests(os.path.join(os.getcwd(), "tests")) loader.load_project_tests(os.path.join(os.getcwd(), "tests"))

View File

@@ -1,7 +1,7 @@
import os import os
import time import time
from httprunner import exceptions, loader, runner from httprunner import exceptions, loader, parser, runner
from httprunner.utils import deep_update_dict from httprunner.utils import deep_update_dict
from tests.api_server import HTTPBIN_SERVER from tests.api_server import HTTPBIN_SERVER
from tests.base import ApiServerUnittest from tests.base import ApiServerUnittest
@@ -37,7 +37,11 @@ class TestRunner(ApiServerUnittest):
for testcase_file_path in testcase_file_path_list: for testcase_file_path in testcase_file_path_list:
testcases = loader.load_file(testcase_file_path) testcases = loader.load_file(testcase_file_path)
testcases = parser.prepare_lazy_data(
testcases,
self.debugtalk_functions,
{"expect_status_code", "token_len", "token", "success"}
)
config_dict = {} config_dict = {}
test_runner = runner.Runner(config_dict, self.debugtalk_functions) test_runner = runner.Runner(config_dict, self.debugtalk_functions)
@@ -83,7 +87,7 @@ class TestRunner(ApiServerUnittest):
"name": "basic test with httpbin", "name": "basic test with httpbin",
"base_url": HTTPBIN_SERVER, "base_url": HTTPBIN_SERVER,
"setup_hooks": [ "setup_hooks": [
"${sleep_N_secs(0.5)}" "${sleep_N_secs(0.5)}",
"${hook_print(setup)}" "${hook_print(setup)}"
], ],
"teardown_hooks": [ "teardown_hooks": [
@@ -91,6 +95,13 @@ class TestRunner(ApiServerUnittest):
"${hook_print(teardown)}" "${hook_print(teardown)}"
] ]
} }
prepared_config_dict = parser.prepare_lazy_data(config_dict, self.debugtalk_functions)
test_runner = runner.Runner(prepared_config_dict, self.debugtalk_functions)
end_time = time.time()
# check if testcase setup hook executed
self.assertGreater(end_time - start_time, 0.5)
start_time = time.time()
test = { test = {
"name": "get token", "name": "get token",
"request": { "request": {
@@ -111,12 +122,6 @@ class TestRunner(ApiServerUnittest):
{"check": "status_code", "expect": 200} {"check": "status_code", "expect": 200}
] ]
} }
test_runner = runner.Runner(config_dict, self.debugtalk_functions)
end_time = time.time()
# check if testcase setup hook executed
self.assertGreater(end_time - start_time, 0.5)
start_time = time.time()
test_runner.run_test(test) test_runner.run_test(test)
test_runner.run_test(test) test_runner.run_test(test)
end_time = time.time() end_time = time.time()
@@ -130,6 +135,7 @@ class TestRunner(ApiServerUnittest):
} }
test = { test = {
"name": "modify request headers", "name": "modify request headers",
"base_url": HTTPBIN_SERVER,
"request": { "request": {
"url": "/anything", "url": "/anything",
"method": "POST", "method": "POST",
@@ -146,8 +152,9 @@ class TestRunner(ApiServerUnittest):
{"check": "status_code", "expect": 200} {"check": "status_code", "expect": 200}
] ]
} }
parsed_test = parser.prepare_lazy_data(test, self.debugtalk_functions)
test_runner = runner.Runner(config_dict, self.debugtalk_functions) test_runner = runner.Runner(config_dict, self.debugtalk_functions)
test_runner.run_test(test) test_runner.run_test(parsed_test)
test_variables_mapping = test_runner.session_context.test_variables_mapping test_variables_mapping = test_runner.session_context.test_variables_mapping
self.assertEqual(test_variables_mapping["total"], 6) self.assertEqual(test_variables_mapping["total"], 6)
self.assertEqual(test_variables_mapping["request"]["data"], "a=1&b=2") self.assertEqual(test_variables_mapping["request"]["data"], "a=1&b=2")
@@ -159,6 +166,7 @@ class TestRunner(ApiServerUnittest):
} }
test = { test = {
"name": "modify request headers", "name": "modify request headers",
"base_url": HTTPBIN_SERVER,
"request": { "request": {
"url": "/anything", "url": "/anything",
"method": "POST", "method": "POST",
@@ -180,7 +188,8 @@ class TestRunner(ApiServerUnittest):
] ]
} }
test_runner = runner.Runner(config_dict, self.debugtalk_functions) test_runner = runner.Runner(config_dict, self.debugtalk_functions)
test_runner.run_test(test) parsed_test = parser.prepare_lazy_data(test, self.debugtalk_functions, {"request"})
test_runner.run_test(parsed_test)
def test_run_testcase_with_teardown_hooks_success(self): def test_run_testcase_with_teardown_hooks_success(self):
test = { test = {
@@ -232,8 +241,9 @@ class TestRunner(ApiServerUnittest):
], ],
"teardown_hooks": ["${teardown_hook_sleep_N_secs($response, 2)}"] "teardown_hooks": ["${teardown_hook_sleep_N_secs($response, 2)}"]
} }
prepared_test = parser.prepare_lazy_data(test, self.debugtalk_functions, {"response"})
start_time = time.time() start_time = time.time()
self.test_runner.run_test(test) self.test_runner.run_test(prepared_test)
end_time = time.time() end_time = time.time()
# check if teardown function executed # check if teardown function executed
self.assertGreater(end_time - start_time, 2) self.assertGreater(end_time - start_time, 2)