mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-06 16:29:37 +08:00
refactor hook mechanism:
1, remove EventHook; 2, setup_hooks: could reference request dict; 3, teardown_hooks: could reference Response object.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
__title__ = 'HttpRunner'
|
__title__ = 'HttpRunner'
|
||||||
__description__ = 'One-stop solution for HTTP(S) testing.'
|
__description__ = 'One-stop solution for HTTP(S) testing.'
|
||||||
__url__ = 'https://github.com/HttpRunner/HttpRunner'
|
__url__ = 'https://github.com/HttpRunner/HttpRunner'
|
||||||
__version__ = '1.4.2'
|
__version__ = '1.4.3'
|
||||||
__author__ = 'debugtalk'
|
__author__ = 'debugtalk'
|
||||||
__author_email__ = 'mail@debugtalk.com'
|
__author_email__ = 'mail@debugtalk.com'
|
||||||
__license__ = 'MIT'
|
__license__ = 'MIT'
|
||||||
|
|||||||
@@ -132,25 +132,25 @@ def endswith(check_value, expect_value):
|
|||||||
|
|
||||||
""" built-in hooks
|
""" built-in hooks
|
||||||
"""
|
"""
|
||||||
def setup_hook_prepare_kwargs(method, url, kwargs):
|
def setup_hook_prepare_kwargs(request):
|
||||||
if method == "POST":
|
if request["method"] == "POST":
|
||||||
content_type = kwargs.get("headers", {}).get("content-type")
|
content_type = request.get("headers", {}).get("content-type")
|
||||||
if content_type and "data" in kwargs:
|
if content_type and "data" in request:
|
||||||
# if request content-type is application/json, request data should be dumped
|
# if request content-type is application/json, request data should be dumped
|
||||||
if content_type.startswith("application/json") and isinstance(kwargs["data"], (dict, list)):
|
if content_type.startswith("application/json") and isinstance(request["data"], (dict, list)):
|
||||||
kwargs["data"] = json.dumps(kwargs["data"])
|
request["data"] = json.dumps(request["data"])
|
||||||
|
|
||||||
if isinstance(kwargs["data"], str):
|
if isinstance(request["data"], str):
|
||||||
kwargs["data"] = kwargs["data"].encode('utf-8')
|
request["data"] = request["data"].encode('utf-8')
|
||||||
|
|
||||||
def setup_hook_httpntlmauth(method, url, kwargs):
|
def setup_hook_httpntlmauth(request):
|
||||||
if "httpntlmauth" in kwargs:
|
if "httpntlmauth" in request:
|
||||||
from requests_ntlm import HttpNtlmAuth
|
from requests_ntlm import HttpNtlmAuth
|
||||||
auth_account = kwargs.pop("httpntlmauth")
|
auth_account = request.pop("httpntlmauth")
|
||||||
kwargs["auth"] = HttpNtlmAuth(
|
request["auth"] = HttpNtlmAuth(
|
||||||
auth_account["username"], auth_account["password"])
|
auth_account["username"], auth_account["password"])
|
||||||
|
|
||||||
def teardown_hook_sleep_1_secs(resp_obj):
|
def sleep_N_secs(n_secs):
|
||||||
""" sleep 1 seconds after request
|
""" sleep n seconds
|
||||||
"""
|
"""
|
||||||
time.sleep(1)
|
time.sleep(n_secs)
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
# encoding: utf-8
|
|
||||||
from httprunner.exception import MyBaseError
|
|
||||||
|
|
||||||
|
|
||||||
class EventHook(object):
|
|
||||||
"""
|
|
||||||
Simple event class used to provide hooks for different types of events in HttpRunner.
|
|
||||||
|
|
||||||
Here's how to use the EventHook class::
|
|
||||||
|
|
||||||
my_event = EventHook()
|
|
||||||
def on_my_event(a, b, **kw):
|
|
||||||
print "Event was fired with arguments: %s, %s" % (a, b)
|
|
||||||
my_event += on_my_event
|
|
||||||
my_event.fire(a="foo", b="bar")
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._handlers = []
|
|
||||||
|
|
||||||
def __iadd__(self, handler):
|
|
||||||
self._handlers.append(handler)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __isub__(self, handler):
|
|
||||||
if handler not in self._handlers:
|
|
||||||
raise MyBaseError("handler not found: {}".format(handler))
|
|
||||||
|
|
||||||
index = self._handlers.index(handler)
|
|
||||||
self._handlers.pop(index)
|
|
||||||
return self
|
|
||||||
|
|
||||||
def fire(self, **kwargs):
|
|
||||||
for handler in self._handlers:
|
|
||||||
handler(**kwargs)
|
|
||||||
@@ -5,7 +5,6 @@ from unittest.case import SkipTest
|
|||||||
from httprunner import exception, logger, response, utils
|
from httprunner import exception, logger, response, utils
|
||||||
from httprunner.client import HttpSession
|
from httprunner.client import HttpSession
|
||||||
from httprunner.context import Context
|
from httprunner.context import Context
|
||||||
from httprunner.events import EventHook
|
|
||||||
|
|
||||||
|
|
||||||
class Runner(object):
|
class Runner(object):
|
||||||
@@ -94,45 +93,10 @@ class Runner(object):
|
|||||||
if skip_reason:
|
if skip_reason:
|
||||||
raise SkipTest(skip_reason)
|
raise SkipTest(skip_reason)
|
||||||
|
|
||||||
def _prepare_hooks_event(self, hooks):
|
def do_hook_actions(self, actions):
|
||||||
if not hooks:
|
for action in actions:
|
||||||
return None
|
logger.log_debug("call hook: {}".format(action))
|
||||||
|
self.context.eval_content(action)
|
||||||
event = EventHook()
|
|
||||||
for hook in hooks:
|
|
||||||
func = self.context.testcase_parser.get_bind_function(hook)
|
|
||||||
event += func
|
|
||||||
|
|
||||||
return event
|
|
||||||
|
|
||||||
def _call_setup_hooks(self, hooks, method, url, kwargs):
|
|
||||||
""" call hook functions before request
|
|
||||||
|
|
||||||
Listeners should take the following arguments:
|
|
||||||
|
|
||||||
* *method*: request method type, e.g. GET, POST, PUT
|
|
||||||
* *url*: URL that was called (or override name if it was used in the call to the client)
|
|
||||||
* *kwargs*: kwargs of request
|
|
||||||
"""
|
|
||||||
hooks.insert(0, "setup_hook_prepare_kwargs")
|
|
||||||
event = self._prepare_hooks_event(hooks)
|
|
||||||
if not event:
|
|
||||||
return
|
|
||||||
|
|
||||||
event.fire(method=method, url=url, kwargs=kwargs)
|
|
||||||
|
|
||||||
def _call_teardown_hooks(self, hooks, resp_obj):
|
|
||||||
""" call hook functions after request
|
|
||||||
|
|
||||||
Listeners should take the following arguments:
|
|
||||||
|
|
||||||
* *resp_obj*: response object
|
|
||||||
"""
|
|
||||||
event = self._prepare_hooks_event(hooks)
|
|
||||||
if not event:
|
|
||||||
return
|
|
||||||
|
|
||||||
event.fire(resp_obj=resp_obj)
|
|
||||||
|
|
||||||
def run_test(self, testcase_dict):
|
def run_test(self, testcase_dict):
|
||||||
""" run single testcase.
|
""" run single testcase.
|
||||||
@@ -161,7 +125,12 @@ class Runner(object):
|
|||||||
}
|
}
|
||||||
@return True or raise exception during test
|
@return True or raise exception during test
|
||||||
"""
|
"""
|
||||||
|
# check skip
|
||||||
|
self._handle_skip_feature(testcase_dict)
|
||||||
|
|
||||||
|
# prepare
|
||||||
parsed_request = self.init_config(testcase_dict, level="testcase")
|
parsed_request = self.init_config(testcase_dict, level="testcase")
|
||||||
|
self.context.bind_variables({"request": parsed_request})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
url = parsed_request.pop('url')
|
url = parsed_request.pop('url')
|
||||||
@@ -170,28 +139,36 @@ class Runner(object):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
raise exception.ParamsError("URL or METHOD missed!")
|
raise exception.ParamsError("URL or METHOD missed!")
|
||||||
|
|
||||||
self._handle_skip_feature(testcase_dict)
|
|
||||||
|
|
||||||
extractors = testcase_dict.get("extract", []) or testcase_dict.get("extractors", [])
|
|
||||||
validators = testcase_dict.get("validate", []) or testcase_dict.get("validators", [])
|
|
||||||
setup_hooks = testcase_dict.get("setup_hooks", [])
|
|
||||||
teardown_hooks = testcase_dict.get("teardown_hooks", [])
|
|
||||||
|
|
||||||
logger.log_info("{method} {url}".format(method=method, url=url))
|
logger.log_info("{method} {url}".format(method=method, url=url))
|
||||||
logger.log_debug("request kwargs(raw): {kwargs}".format(kwargs=parsed_request))
|
logger.log_debug("request kwargs(raw): {kwargs}".format(kwargs=parsed_request))
|
||||||
self._call_setup_hooks(setup_hooks, method, url, parsed_request)
|
|
||||||
|
# setup hooks
|
||||||
|
setup_hooks = testcase_dict.get("setup_hooks", [])
|
||||||
|
setup_hooks.insert(0, "${setup_hook_prepare_kwargs($request)}")
|
||||||
|
self.do_hook_actions(setup_hooks)
|
||||||
|
|
||||||
|
# request
|
||||||
resp = self.http_client_session.request(
|
resp = self.http_client_session.request(
|
||||||
method,
|
method,
|
||||||
url,
|
url,
|
||||||
name=group_name,
|
name=group_name,
|
||||||
**parsed_request
|
**parsed_request
|
||||||
)
|
)
|
||||||
self._call_teardown_hooks(teardown_hooks, resp)
|
|
||||||
resp_obj = response.ResponseObject(resp)
|
|
||||||
|
|
||||||
|
# teardown hooks
|
||||||
|
teardown_hooks = testcase_dict.get("teardown_hooks", [])
|
||||||
|
if teardown_hooks:
|
||||||
|
self.context.bind_variables({"response": resp})
|
||||||
|
self.do_hook_actions(teardown_hooks)
|
||||||
|
|
||||||
|
# extract
|
||||||
|
extractors = testcase_dict.get("extract", []) or testcase_dict.get("extractors", [])
|
||||||
|
resp_obj = response.ResponseObject(resp)
|
||||||
extracted_variables_mapping = resp_obj.extract_response(extractors)
|
extracted_variables_mapping = resp_obj.extract_response(extractors)
|
||||||
self.context.bind_extracted_variables(extracted_variables_mapping)
|
self.context.bind_extracted_variables(extracted_variables_mapping)
|
||||||
|
|
||||||
|
# validate
|
||||||
|
validators = testcase_dict.get("validate", []) or testcase_dict.get("validators", [])
|
||||||
try:
|
try:
|
||||||
self.context.validate(validators, resp_obj)
|
self.context.validate(validators, resp_obj)
|
||||||
except (exception.ParamsError, exception.ResponseError, \
|
except (exception.ParamsError, exception.ResponseError, \
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import random
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from httprunner import exception, logger, utils
|
from httprunner import exception, logger, utils
|
||||||
from httprunner.compat import OrderedDict, numeric_types
|
from httprunner.compat import OrderedDict, basestring, numeric_types
|
||||||
from httprunner.utils import FileUtils
|
from httprunner.utils import FileUtils
|
||||||
|
|
||||||
variable_regexp = r"\$([\w_]+)"
|
variable_regexp = r"\$([\w_]+)"
|
||||||
@@ -75,14 +75,15 @@ def parse_function(content):
|
|||||||
func(a=1, b=2) => {'func_name': 'func', 'args': [], 'kwargs': {'a': 1, 'b': 2}}
|
func(a=1, b=2) => {'func_name': 'func', 'args': [], 'kwargs': {'a': 1, 'b': 2}}
|
||||||
func(1, 2, a=3, b=4) => {'func_name': 'func', 'args': [1, 2], 'kwargs': {'a':3, 'b':4}}
|
func(1, 2, a=3, b=4) => {'func_name': 'func', 'args': [1, 2], 'kwargs': {'a':3, 'b':4}}
|
||||||
"""
|
"""
|
||||||
|
matched = function_regexp_compile.match(content)
|
||||||
|
if not matched:
|
||||||
|
raise exception.FunctionNotFound("{} not found!".format(content))
|
||||||
|
|
||||||
function_meta = {
|
function_meta = {
|
||||||
|
"func_name": matched.group(1),
|
||||||
"args": [],
|
"args": [],
|
||||||
"kwargs": {}
|
"kwargs": {}
|
||||||
}
|
}
|
||||||
matched = function_regexp_compile.match(content)
|
|
||||||
if not matched:
|
|
||||||
raise exception.ApiNotFound("{} not found!".format(content))
|
|
||||||
function_meta["func_name"] = matched.group(1)
|
|
||||||
|
|
||||||
args_str = matched.group(2).replace(" ", "")
|
args_str = matched.group(2).replace(" ", "")
|
||||||
if args_str == "":
|
if args_str == "":
|
||||||
@@ -597,6 +598,7 @@ def substitute_variables_with_mapping(content, mapping):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
# TODO: refactor type check
|
||||||
if isinstance(content, bool):
|
if isinstance(content, bool):
|
||||||
return content
|
return content
|
||||||
|
|
||||||
@@ -903,17 +905,16 @@ class TestcaseParser(object):
|
|||||||
|
|
||||||
return evaluated_data
|
return evaluated_data
|
||||||
|
|
||||||
if isinstance(content, (numeric_types, type)):
|
if isinstance(content, basestring):
|
||||||
return content
|
|
||||||
|
|
||||||
# content is in string format here
|
# content is in string format here
|
||||||
content = content.strip()
|
content = content.strip()
|
||||||
|
|
||||||
# replace functions with evaluated value
|
# replace functions with evaluated value
|
||||||
# Notice: _eval_content_functions must be called before _eval_content_variables
|
# Notice: _eval_content_functions must be called before _eval_content_variables
|
||||||
content = self._eval_content_functions(content)
|
content = self._eval_content_functions(content)
|
||||||
|
|
||||||
# replace variables with binding value
|
# replace variables with binding value
|
||||||
content = self._eval_content_variables(content)
|
content = self._eval_content_variables(content)
|
||||||
|
|
||||||
return content
|
return content
|
||||||
|
|||||||
@@ -68,8 +68,16 @@ def gen_random_string(str_len):
|
|||||||
random_string = ''.join(random_char_list)
|
random_string = ''.join(random_char_list)
|
||||||
return random_string
|
return random_string
|
||||||
|
|
||||||
def setup_hook_add_kwargs(method, url, kwargs):
|
def setup_hook_add_kwargs(request):
|
||||||
kwargs["key"] = "value"
|
request["key"] = "value"
|
||||||
|
|
||||||
def setup_hook_remove_kwargs(method, url, kwargs):
|
def setup_hook_remove_kwargs(request):
|
||||||
kwargs.pop("key")
|
request.pop("key")
|
||||||
|
|
||||||
|
def teardown_hook_sleep_N_secs(response, n_secs):
|
||||||
|
""" sleep n seconds after request
|
||||||
|
"""
|
||||||
|
if response.status_code == 200:
|
||||||
|
time.sleep(0.1)
|
||||||
|
else:
|
||||||
|
time.sleep(n_secs)
|
||||||
|
|||||||
@@ -9,8 +9,10 @@
|
|||||||
url: /headers
|
url: /headers
|
||||||
method: GET
|
method: GET
|
||||||
setup_hooks:
|
setup_hooks:
|
||||||
- setup_hook_add_kwargs
|
- ${setup_hook_add_kwargs($request)}
|
||||||
- setup_hook_remove_kwargs
|
- ${setup_hook_remove_kwargs($request)}
|
||||||
|
teardown_hooks:
|
||||||
|
- ${teardown_hook_sleep_N_secs($response, 1)}
|
||||||
validate:
|
validate:
|
||||||
- eq: ["status_code", 200]
|
- eq: ["status_code", 200]
|
||||||
- eq: [content.headers.Host, "127.0.0.1:3458"]
|
- eq: [content.headers.Host, "127.0.0.1:3458"]
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ class TestHttpClient(ApiServerUnittest):
|
|||||||
self.assertEqual(True, resp.json()['success'])
|
self.assertEqual(True, resp.json()['success'])
|
||||||
|
|
||||||
def test_prepare_kwargs_content_type_application_json_without_charset(self):
|
def test_prepare_kwargs_content_type_application_json_without_charset(self):
|
||||||
kwargs = {
|
request = {
|
||||||
|
"url": "/path",
|
||||||
|
"method": "POST",
|
||||||
"headers": {
|
"headers": {
|
||||||
"content-type": "application/json"
|
"content-type": "application/json"
|
||||||
},
|
},
|
||||||
@@ -49,13 +51,15 @@ class TestHttpClient(ApiServerUnittest):
|
|||||||
"b": 2
|
"b": 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setup_hook_prepare_kwargs("POST", "/path", kwargs)
|
setup_hook_prepare_kwargs(request)
|
||||||
self.assertIsInstance(kwargs["data"], bytes)
|
self.assertIsInstance(request["data"], bytes)
|
||||||
self.assertIn(b'"a": 1', kwargs["data"])
|
self.assertIn(b'"a": 1', request["data"])
|
||||||
self.assertIn(b'"b": 2', kwargs["data"])
|
self.assertIn(b'"b": 2', request["data"])
|
||||||
|
|
||||||
def test_prepare_kwargs_content_type_application_json_charset_utf8(self):
|
def test_prepare_kwargs_content_type_application_json_charset_utf8(self):
|
||||||
kwargs = {
|
request = {
|
||||||
|
"url": "/path",
|
||||||
|
"method": "POST",
|
||||||
"headers": {
|
"headers": {
|
||||||
"content-type": "application/json; charset=utf-8"
|
"content-type": "application/json; charset=utf-8"
|
||||||
},
|
},
|
||||||
@@ -64,5 +68,5 @@ class TestHttpClient(ApiServerUnittest):
|
|||||||
"b": 2
|
"b": 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setup_hook_prepare_kwargs("POST", "/path", kwargs)
|
setup_hook_prepare_kwargs(request)
|
||||||
self.assertIsInstance(kwargs["data"], bytes)
|
self.assertIsInstance(request["data"], bytes)
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ class VariableBindsUnittest(ApiServerUnittest):
|
|||||||
|
|
||||||
def test_exec_content_functions(self):
|
def test_exec_content_functions(self):
|
||||||
test_runner = runner.Runner()
|
test_runner = runner.Runner()
|
||||||
content = "${teardown_hook_sleep_1_secs(1)}"
|
content = "${sleep_N_secs(1)}"
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
test_runner.context.eval_content(content)
|
test_runner.context.eval_content(content)
|
||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
|
|||||||
@@ -60,29 +60,91 @@ class TestRunner(ApiServerUnittest):
|
|||||||
"sign": "f1219719911caae89ccc301679857ebfda115ca2"
|
"sign": "f1219719911caae89ccc301679857ebfda115ca2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"extract": [
|
|
||||||
{"token": "content.token"}
|
|
||||||
],
|
|
||||||
"validate": [
|
"validate": [
|
||||||
{"check": "status_code", "expect": 205},
|
{"check": "status_code", "expect": 205},
|
||||||
{"check": "content.token", "comparator": "len_eq", "expect": 19}
|
{"check": "content.token", "comparator": "len_eq", "expect": 19}
|
||||||
],
|
]
|
||||||
"teardown_hooks": ["teardown_hook_sleep_1_secs"]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
with self.assertRaises(exception.ValidationError):
|
with self.assertRaises(exception.ValidationError):
|
||||||
start_time = time.time()
|
|
||||||
self.test_runner.run_test(test)
|
self.test_runner.run_test(test)
|
||||||
end_time = time.time()
|
|
||||||
# check if teardown function executed
|
|
||||||
self.assertGreater(end_time - start_time, 2)
|
|
||||||
|
|
||||||
def test_run_testset_with_setup_hooks(self):
|
def test_run_testset_with_setup_hooks(self):
|
||||||
testcase_file_path = os.path.join(
|
testcase_file_path = os.path.join(
|
||||||
os.getcwd(), 'tests/httpbin/hooks.yml')
|
os.getcwd(), 'tests/httpbin/hooks.yml')
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
runner = HttpRunner().run(testcase_file_path)
|
runner = HttpRunner().run(testcase_file_path)
|
||||||
|
end_time = time.time()
|
||||||
summary = runner.summary
|
summary = runner.summary
|
||||||
self.assertTrue(summary["success"])
|
self.assertTrue(summary["success"])
|
||||||
|
self.assertLess(end_time - start_time, 1)
|
||||||
|
|
||||||
|
def test_run_testset_with_teardown_hooks_success(self):
|
||||||
|
test = {
|
||||||
|
"name": "get token",
|
||||||
|
"request": {
|
||||||
|
"url": "http://127.0.0.1:5000/api/get-token",
|
||||||
|
"method": "POST",
|
||||||
|
"headers": {
|
||||||
|
"content-type": "application/json",
|
||||||
|
"user_agent": "iOS/10.3",
|
||||||
|
"device_sn": "HZfFBh6tU59EdXJ",
|
||||||
|
"os_platform": "ios",
|
||||||
|
"app_version": "2.8.6"
|
||||||
|
},
|
||||||
|
"json": {
|
||||||
|
"sign": "f1219719911caae89ccc301679857ebfda115ca2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"validate": [
|
||||||
|
{"check": "status_code", "expect": 200}
|
||||||
|
],
|
||||||
|
"teardown_hooks": ["${teardown_hook_sleep_N_secs($response, 2)}"]
|
||||||
|
}
|
||||||
|
config_dict = {
|
||||||
|
"path": os.path.join(os.getcwd(), __file__)
|
||||||
|
}
|
||||||
|
self.test_runner.init_config(config_dict, "testset")
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
self.test_runner.run_test(test)
|
||||||
|
end_time = time.time()
|
||||||
|
# check if teardown function executed
|
||||||
|
self.assertLess(end_time - start_time, 0.5)
|
||||||
|
|
||||||
|
def test_run_testset_with_teardown_hooks_fail(self):
|
||||||
|
test = {
|
||||||
|
"name": "get token",
|
||||||
|
"request": {
|
||||||
|
"url": "http://127.0.0.1:5000/api/get-token2",
|
||||||
|
"method": "POST",
|
||||||
|
"headers": {
|
||||||
|
"content-type": "application/json",
|
||||||
|
"user_agent": "iOS/10.3",
|
||||||
|
"device_sn": "HZfFBh6tU59EdXJ",
|
||||||
|
"os_platform": "ios",
|
||||||
|
"app_version": "2.8.6"
|
||||||
|
},
|
||||||
|
"json": {
|
||||||
|
"sign": "f1219719911caae89ccc301679857ebfda115ca2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"validate": [
|
||||||
|
{"check": "status_code", "expect": 404}
|
||||||
|
],
|
||||||
|
"teardown_hooks": ["${teardown_hook_sleep_N_secs($response, 2)}"]
|
||||||
|
}
|
||||||
|
config_dict = {
|
||||||
|
"path": os.path.join(os.getcwd(), __file__)
|
||||||
|
}
|
||||||
|
self.test_runner.init_config(config_dict, "testset")
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
self.test_runner.run_test(test)
|
||||||
|
end_time = time.time()
|
||||||
|
# check if teardown function executed
|
||||||
|
self.assertGreater(end_time - start_time, 2)
|
||||||
|
|
||||||
def test_run_testset_hardcode(self):
|
def test_run_testset_hardcode(self):
|
||||||
for testcase_file_path in self.testcase_file_path_list:
|
for testcase_file_path in self.testcase_file_path_list:
|
||||||
|
|||||||
@@ -454,6 +454,10 @@ class TestcaseParserUnittest(unittest.TestCase):
|
|||||||
testcase.parse_function("func(1, 2, a=3, b=4)"),
|
testcase.parse_function("func(1, 2, a=3, b=4)"),
|
||||||
{'func_name': 'func', 'args': [1, 2], 'kwargs': {'a': 3, 'b': 4}}
|
{'func_name': 'func', 'args': [1, 2], 'kwargs': {'a': 3, 'b': 4}}
|
||||||
)
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
testcase.parse_function("func($request, 123)"),
|
||||||
|
{'func_name': 'func', 'args': ["$request", 123], 'kwargs': {}}
|
||||||
|
)
|
||||||
|
|
||||||
def test_parse_content_with_bindings_variables(self):
|
def test_parse_content_with_bindings_variables(self):
|
||||||
variables = {
|
variables = {
|
||||||
|
|||||||
Reference in New Issue
Block a user