mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-14 04:59:40 +08:00
call HttpRunner class with testsets data structure other than path
This commit is contained in:
@@ -152,30 +152,34 @@ class TaskSuite(unittest.TestSuite):
|
||||
""" create task suite with specified testcase path.
|
||||
each task suite may include one or several test suite.
|
||||
"""
|
||||
def __init__(self, path, mapping=None, http_client_session=None):
|
||||
def __init__(self, testsets, mapping=None, http_client_session=None):
|
||||
"""
|
||||
@params
|
||||
path: path could be in several type
|
||||
- absolute/relative file path
|
||||
- absolute/relative folder path
|
||||
- list/set container with file(s) and/or folder(s)
|
||||
(dict) mapping:
|
||||
testsets (dict/list): testset or list of testset
|
||||
testset_dict
|
||||
or
|
||||
[
|
||||
testset_dict_1,
|
||||
testset_dict_2,
|
||||
{
|
||||
"name": "desc1",
|
||||
"config": {},
|
||||
"api": {},
|
||||
"testcases": [testcase11, testcase12]
|
||||
}
|
||||
]
|
||||
mapping (dict):
|
||||
passed in variables mapping, it will override variables in config block
|
||||
"""
|
||||
super(TaskSuite, self).__init__()
|
||||
mapping = mapping or {}
|
||||
|
||||
if not isinstance(path, list):
|
||||
# absolute/relative file/folder path
|
||||
path = [path]
|
||||
|
||||
# remove duplicate path
|
||||
path = set(path)
|
||||
|
||||
testsets = testcase.load_testcases_by_path(path)
|
||||
if not testsets:
|
||||
raise exception.TestcaseNotFound
|
||||
|
||||
if isinstance(testsets, dict):
|
||||
testsets = [testsets]
|
||||
|
||||
self.suite_list = []
|
||||
for testset in testsets:
|
||||
suite = TestSuite(testset, mapping, http_client_session)
|
||||
@@ -187,6 +191,18 @@ class TaskSuite(unittest.TestSuite):
|
||||
return self.suite_list
|
||||
|
||||
|
||||
def init_task_suite(path_or_testsets, mapping=None, http_client_session=None):
|
||||
""" initialize task suite
|
||||
"""
|
||||
if not testcase.is_testsets(path_or_testsets):
|
||||
testsets = testcase.load_testcases_by_path(path_or_testsets)
|
||||
else:
|
||||
testsets = path_or_testsets
|
||||
|
||||
mapping = mapping or {}
|
||||
return TaskSuite(testsets, mapping, http_client_session)
|
||||
|
||||
|
||||
class HttpRunner(object):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -198,16 +214,25 @@ class HttpRunner(object):
|
||||
kwargs.setdefault("resultclass", HtmlTestResult)
|
||||
self.runner = unittest.TextTestRunner(**kwargs)
|
||||
|
||||
def run(self, path, mapping=None):
|
||||
""" start to run specified testset file with varaibles mapping
|
||||
@param (str) path:
|
||||
YAML/JSON testset file path
|
||||
def run(self, path_or_testsets, mapping=None):
|
||||
""" start to run test with varaibles mapping
|
||||
@param path_or_testsets: YAML/JSON testset file path or testset list
|
||||
path: path could be in several type
|
||||
- absolute/relative file path
|
||||
- absolute/relative folder path
|
||||
- list/set container with file(s) and/or folder(s)
|
||||
testsets: testset or list of testset
|
||||
- (dict) testset_dict
|
||||
- (list) list of testset_dict
|
||||
[
|
||||
testset_dict_1,
|
||||
testset_dict_2
|
||||
]
|
||||
@param (dict) mapping:
|
||||
if mapping specified, it will override variables in config block
|
||||
"""
|
||||
try:
|
||||
mapping = mapping or {}
|
||||
task_suite = TaskSuite(path, mapping)
|
||||
task_suite = init_task_suite(path_or_testsets, mapping)
|
||||
except exception.TestcaseNotFound:
|
||||
logger.log_error("Testcases not found in {}".format(path))
|
||||
sys.exit(1)
|
||||
@@ -238,9 +263,8 @@ class HttpRunner(object):
|
||||
|
||||
class LocustTask(object):
|
||||
|
||||
def __init__(self, path, locust_client, mapping=None):
|
||||
mapping = mapping or {}
|
||||
self.task_suite = TaskSuite(path, mapping, locust_client)
|
||||
def __init__(self, path_or_testsets, locust_client, mapping=None):
|
||||
self.task_suite = init_task_suite(path_or_testsets, mapping, locust_client)
|
||||
|
||||
def run(self):
|
||||
for suite in self.task_suite:
|
||||
|
||||
@@ -417,6 +417,46 @@ def extend_test_api(test_block_dict):
|
||||
test_extracors
|
||||
)
|
||||
|
||||
def is_testset(data_structure):
|
||||
""" check if data_structure is a testset
|
||||
testset should always be in the following data structure:
|
||||
{
|
||||
"name": "desc1",
|
||||
"config": {},
|
||||
"api": {},
|
||||
"testcases": [testcase11, testcase12]
|
||||
}
|
||||
"""
|
||||
if not isinstance(data_structure, dict):
|
||||
return False
|
||||
|
||||
if "name" not in data_structure or "testcases" not in data_structure:
|
||||
return False
|
||||
|
||||
if not isinstance(data_structure["testcases"], list):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def is_testsets(data_structure):
|
||||
""" check if data_structure is testset or testsets
|
||||
testsets should always be in the following data structure:
|
||||
testset_dict
|
||||
or
|
||||
[
|
||||
testset_dict_1,
|
||||
testset_dict_2
|
||||
]
|
||||
"""
|
||||
if not isinstance(data_structure, list):
|
||||
return is_testset(data_structure)
|
||||
|
||||
for item in data_structure:
|
||||
if not is_testset(item):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def load_test_file(file_path):
|
||||
""" load testset file, get testset data structure.
|
||||
@param file_path: absolute valid testset file path
|
||||
@@ -467,7 +507,9 @@ def load_test_file(file_path):
|
||||
testset["api"][func_name] = api_info
|
||||
|
||||
else:
|
||||
logger.log_warning("unexpected block: {}. block should only be config or test.".format(key))
|
||||
logger.log_warning(
|
||||
"unexpected block: {}. block should only be 'config', 'test' or 'api'.".format(key)
|
||||
)
|
||||
|
||||
return testset
|
||||
|
||||
|
||||
@@ -9,6 +9,53 @@ class TestHttpRunner(ApiServerUnittest):
|
||||
|
||||
def setUp(self):
|
||||
self.testset_path = "tests/data/demo_testset_cli.yml"
|
||||
self.testset = {
|
||||
'name': 'testset description',
|
||||
'config': {
|
||||
'path': 'docs/data/demo-quickstart-2.yml',
|
||||
'name': 'testset description',
|
||||
'request': {
|
||||
'base_url': '',
|
||||
'headers': {'User-Agent': 'python-requests/2.18.4'}
|
||||
},
|
||||
'variables': [],
|
||||
'output': ['token']
|
||||
},
|
||||
'api': {},
|
||||
'testcases': [
|
||||
{
|
||||
'name': '/api/get-token',
|
||||
'request': {
|
||||
'url': 'http://127.0.0.1:5000/api/get-token',
|
||||
'method': 'POST',
|
||||
'headers': {'Content-Type': 'application/json', 'app_version': '2.8.6', 'device_sn': 'FwgRiO7CNA50DSU', 'os_platform': 'ios', 'user_agent': 'iOS/10.3'},
|
||||
'json': {'sign': '958a05393efef0ac7c0fb80a7eac45e24fd40c27'}
|
||||
},
|
||||
'extract': [
|
||||
{'token': 'content.token'}
|
||||
],
|
||||
'validate': [
|
||||
{'eq': ['status_code', 200]},
|
||||
{'eq': ['headers.Content-Type', 'application/json']},
|
||||
{'eq': ['content.success', True]}
|
||||
]
|
||||
},
|
||||
{
|
||||
'name': '/api/users/1000',
|
||||
'request': {
|
||||
'url': 'http://127.0.0.1:5000/api/users/1000',
|
||||
'method': 'POST',
|
||||
'headers': {'Content-Type': 'application/json', 'device_sn': 'FwgRiO7CNA50DSU','token': '$token'}, 'json': {'name': 'user1', 'password': '123456'}
|
||||
},
|
||||
'validate': [
|
||||
{'eq': ['status_code', 201]},
|
||||
{'eq': ['headers.Content-Type', 'application/json']},
|
||||
{'eq': ['content.success', True]},
|
||||
{'eq': ['content.msg', 'user created successfully.']}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
self.reset_all()
|
||||
|
||||
def reset_all(self):
|
||||
@@ -35,3 +82,19 @@ class TestHttpRunner(ApiServerUnittest):
|
||||
runner.gen_html_report(html_report_name=output_folder_name)
|
||||
report_save_dir = os.path.join(os.getcwd(), 'reports', output_folder_name)
|
||||
shutil.rmtree(report_save_dir)
|
||||
|
||||
def test_run_testsets(self):
|
||||
testsets = [self.testset]
|
||||
runner = HttpRunner().run(testsets)
|
||||
summary = runner.summary
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(summary["stat"]["testsRun"], 2)
|
||||
self.assertIn("records", summary)
|
||||
|
||||
def test_run_testset(self):
|
||||
testsets = self.testset
|
||||
runner = HttpRunner().run(testsets)
|
||||
summary = runner.summary
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(summary["stat"]["testsRun"], 2)
|
||||
self.assertIn("records", summary)
|
||||
|
||||
@@ -24,9 +24,57 @@ class TestTask(ApiServerUnittest):
|
||||
self.assertIsInstance(testcase, task.TestCase)
|
||||
|
||||
def test_create_task(self):
|
||||
testcase_file_path = os.path.join(os.getcwd(), 'tests/data/demo_testset_variables.yml')
|
||||
task_suite = task.TaskSuite(testcase_file_path)
|
||||
self.assertEqual(task_suite.countTestCases(), 3)
|
||||
testsets = [
|
||||
{
|
||||
'name': 'testset description',
|
||||
'config': {
|
||||
'path': 'docs/data/demo-quickstart-2.yml',
|
||||
'name': 'testset description',
|
||||
'request': {
|
||||
'base_url': '',
|
||||
'headers': {'User-Agent': 'python-requests/2.18.4'}
|
||||
},
|
||||
'variables': [],
|
||||
'output': ['token']
|
||||
},
|
||||
'api': {},
|
||||
'testcases': [
|
||||
{
|
||||
'name': '/api/get-token',
|
||||
'request': {
|
||||
'url': 'http://127.0.0.1:5000/api/get-token',
|
||||
'method': 'POST',
|
||||
'headers': {'Content-Type': 'application/json', 'app_version': '2.8.6', 'device_sn': 'FwgRiO7CNA50DSU', 'os_platform': 'ios', 'user_agent': 'iOS/10.3'},
|
||||
'json': {'sign': '958a05393efef0ac7c0fb80a7eac45e24fd40c27'}
|
||||
},
|
||||
'extract': [
|
||||
{'token': 'content.token'}
|
||||
],
|
||||
'validate': [
|
||||
{'eq': ['status_code', 200]},
|
||||
{'eq': ['headers.Content-Type', 'application/json']},
|
||||
{'eq': ['content.success', True]}
|
||||
]
|
||||
},
|
||||
{
|
||||
'name': '/api/users/1000',
|
||||
'request': {
|
||||
'url': 'http://127.0.0.1:5000/api/users/1000',
|
||||
'method': 'POST',
|
||||
'headers': {'Content-Type': 'application/json', 'device_sn': 'FwgRiO7CNA50DSU','token': '$token'}, 'json': {'name': 'user1', 'password': '123456'}
|
||||
},
|
||||
'validate': [
|
||||
{'eq': ['status_code', 201]},
|
||||
{'eq': ['headers.Content-Type', 'application/json']},
|
||||
{'eq': ['content.success', True]},
|
||||
{'eq': ['content.msg', 'user created successfully.']}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
task_suite = task.TaskSuite(testsets)
|
||||
self.assertEqual(task_suite.countTestCases(), 2)
|
||||
for suite in task_suite:
|
||||
for testcase in suite:
|
||||
self.assertIsInstance(testcase, task.TestCase)
|
||||
|
||||
@@ -738,3 +738,32 @@ class TestcaseParserUnittest(unittest.TestCase):
|
||||
{"var3": "val3"},
|
||||
merged_extractors
|
||||
)
|
||||
|
||||
def test_is_testsets(self):
|
||||
data_structure = "path/to/file"
|
||||
self.assertFalse(testcase.is_testsets(data_structure))
|
||||
data_structure = ["path/to/file1", "path/to/file2"]
|
||||
self.assertFalse(testcase.is_testsets(data_structure))
|
||||
|
||||
data_structure = {
|
||||
"name": "desc1",
|
||||
"config": {},
|
||||
"api": {},
|
||||
"testcases": ["testcase11", "testcase12"]
|
||||
}
|
||||
self.assertTrue(data_structure)
|
||||
data_structure = [
|
||||
{
|
||||
"name": "desc1",
|
||||
"config": {},
|
||||
"api": {},
|
||||
"testcases": ["testcase11", "testcase12"]
|
||||
},
|
||||
{
|
||||
"name": "desc2",
|
||||
"config": {},
|
||||
"api": {},
|
||||
"testcases": ["testcase21", "testcase22"]
|
||||
}
|
||||
]
|
||||
self.assertTrue(data_structure)
|
||||
|
||||
Reference in New Issue
Block a user