support run test suites set file

This commit is contained in:
httprunner
2017-09-24 14:09:25 +08:00
parent 2513886863
commit 8fb3e0b73a
4 changed files with 93 additions and 91 deletions

View File

@@ -1 +1 @@
__version__ = '0.7.2' __version__ = '0.7.3'

View File

@@ -1,6 +1,6 @@
from collections import OrderedDict from collections import OrderedDict
from ate import exception, response, utils from ate import exception, response, testcase, utils
from ate.client import HttpSession from ate.client import HttpSession
from ate.context import Context from ate.context import Context
@@ -10,6 +10,7 @@ class Runner(object):
def __init__(self, http_client_session=None): def __init__(self, http_client_session=None):
self.http_client_session = http_client_session self.http_client_session = http_client_session
self.context = Context() self.context = Context()
testcase.load_test_dependencies()
def init_config(self, config_dict, level): def init_config(self, config_dict, level):
""" create/update context variables binds """ create/update context variables binds

View File

@@ -7,7 +7,11 @@ from ate import exception, utils
variable_regexp = r"\$([\w_]+)" variable_regexp = r"\$([\w_]+)"
function_regexp = r"\$\{([\w_]+\([\$\w_ =,]*\))\}" function_regexp = r"\$\{([\w_]+\([\$\w_ =,]*\))\}"
function_regexp_compile = re.compile(r"^([\w_]+)\(([\$\w_ =,]*)\)$") function_regexp_compile = re.compile(r"^([\w_]+)\(([\$\w_ =,]*)\)$")
test_def_overall_dict = {} test_def_overall_dict = {
"loaded": False,
"api": {},
"suite": {}
}
def extract_variables(content): def extract_variables(content):
@@ -88,6 +92,37 @@ def parse_function(content):
return function_meta return function_meta
def load_test_dependencies():
""" load all api and suite definitions.
default api folder is "$CWD/tests/api/".
default suite folder is "$CWD/tests/suite/".
"""
test_def_overall_dict["loaded"] = True
test_def_overall_dict["api"] = {}
test_def_overall_dict["suite"] = {}
# load api definitions
api_def_folder = os.path.join(os.getcwd(), "tests", "api")
api_files = utils.load_folder_files(api_def_folder)
for test_file in api_files:
testset = load_test_file(test_file)
test_def_overall_dict["api"].update(testset["api"])
# load suite definitions
suite_def_folder = os.path.join(os.getcwd(), "tests", "suite")
suite_files = utils.load_folder_files(suite_def_folder)
for suite_file in suite_files:
suite = load_test_file(suite_file)
if "def" not in suite["config"]:
raise exception.ParamsError("def missed in suite file: {}!".format(suite_file))
call_func = suite["config"]["def"]
function_meta = parse_function(call_func)
suite["function_meta"] = function_meta
test_def_overall_dict["suite"][function_meta["func_name"]] = suite
def load_testcases_by_path(path): def load_testcases_by_path(path):
""" load testcases from file path """ load testcases from file path
@param path: path could be in several type @param path: path could be in several type
@@ -101,13 +136,15 @@ def load_testcases_by_path(path):
] ]
""" """
if isinstance(path, (list, set)): if isinstance(path, (list, set)):
testsets_list = [] testsets = []
for file_path in set(path): for file_path in set(path):
_testsets_list = load_testcases_by_path(file_path) testset = load_testcases_by_path(file_path)
testsets_list.extend(_testsets_list) if not testset:
continue
testsets.extend(testset)
return testsets_list return testsets
if not os.path.isabs(path): if not os.path.isabs(path):
path = os.path.join(os.getcwd(), path) path = os.path.join(os.getcwd(), path)
@@ -120,10 +157,8 @@ def load_testcases_by_path(path):
testset = load_test_file(path) testset = load_test_file(path)
if testset["testcases"] or testset["api"]: if testset["testcases"] or testset["api"]:
return [testset] return [testset]
else:
return [] return []
else:
return []
def load_test_file(file_path): def load_test_file(file_path):
""" load testset file, get testset data structure. """ load testset file, get testset data structure.
@@ -155,13 +190,16 @@ def load_test_file(file_path):
elif key == "test": elif key == "test":
test_block_dict = item["test"] test_block_dict = item["test"]
if "api" in test_block_dict: if "api" in test_block_dict:
testcase_list = load_testcases_by_call(test_block_dict, "api") ref_name = test_block_dict["api"]
test_info = get_testinfo_by_reference(ref_name, "api")
test_block_dict.update(test_info)
testset["testcases"].append(test_block_dict)
elif "suite" in test_block_dict: elif "suite" in test_block_dict:
testcase_list = load_testcases_by_call(test_block_dict, "suite") ref_name = test_block_dict["suite"]
test_info = get_testinfo_by_reference(ref_name, "suite")
testset["testcases"].extend(test_info["testcases"])
else: else:
testcase_list = [test_block_dict] testset["testcases"].append(test_block_dict)
testset["testcases"].extend(testcase_list)
elif key == "api": elif key == "api":
api_def = item["api"].pop("def") api_def = item["api"].pop("def")
@@ -175,94 +213,56 @@ def load_test_file(file_path):
return testset return testset
def load_testcases_by_call(test_block_dict, call_type): def get_testinfo_by_reference(ref_name, ref_type):
call_func = test_block_dict[call_type] """ get test content by reference name
function_meta = parse_function(call_func) @params:
ref_name: reference name, e.g. api_v1_Account_Login_POST($UserName, $Password)
ref_type: "api" or "suite"
"""
function_meta = parse_function(ref_name)
func_name = function_meta["func_name"] func_name = function_meta["func_name"]
api_call_args = function_meta["args"] call_args = function_meta["args"]
test_info = get_test_definition(func_name, call_type) test_info = get_test_definition(func_name, ref_type)
api_def_args = test_info.get("function_meta").get("args", []) def_args = test_info.get("function_meta").get("args", [])
if len(api_call_args) != len(api_def_args): if len(call_args) != len(def_args):
raise exception.ParamsError("api call args invalid!") raise exception.ParamsError("call args mismatch defined args!")
args_mapping = {} args_mapping = {}
for index, item in enumerate(api_def_args): for index, item in enumerate(def_args):
if api_call_args[index] == item: if call_args[index] == item:
continue continue
args_mapping[item] = api_call_args[index] args_mapping[item] = call_args[index]
if args_mapping: if args_mapping:
test_info = substitute_variables_with_mapping(test_info, args_mapping) test_info = substitute_variables_with_mapping(test_info, args_mapping)
test_block_dict.update(test_info) return test_info
return [test_block_dict] def get_test_definition(name, ref_type):
""" get expected api or suite.
def get_test_definition(name, call_type, dir_path=None):
""" get expected api or suite from dir_path.
@params: @params:
name: api name name: api or suite name
call_type: "api" or "suite" ref_type: "api" or "suite"
dir_path: specified api dir path, default is "$CWD/tests/api/"
@return @return
expected api info if found, otherwise raise ApiNotFound exception expected api info if found, otherwise raise ApiNotFound exception
""" """
global test_def_overall_dict if not test_def_overall_dict.get("loaded", False):
if call_type not in test_def_overall_dict: load_test_dependencies()
test_def_overall_dict[call_type] = {}
test_def_overall_dict[call_type].update(load_test_definition(call_type, dir_path)) test_info = test_def_overall_dict.get(ref_type, {}).get(name)
test_info = test_def_overall_dict[call_type].get(name)
if not test_info: if not test_info:
err_msg = "{} {} not found!".format(call_type, name) err_msg = "{} {} not found!".format(ref_type, name)
if call_type == "api": if ref_type == "api":
raise exception.ApiNotFound(err_msg) raise exception.ApiNotFound(err_msg)
elif call_type == "suite": elif ref_type == "suite":
raise exception.SuiteNotFound(err_msg) raise exception.SuiteNotFound(err_msg)
else: else:
raise exception.ParamsError("call_type can only be api or suite!") raise exception.ParamsError("ref_type can only be api or suite!")
return test_info return test_info
def load_test_definition(call_type, dir_path=None):
""" load all api or suite definitions in specified dir path.
@params:
call_type: "api" or "suite"
dir_path: specified api dir path, default is "$CWD/tests/api/"
@return (dict) all api definitions in dir_path merged in one dict
"""
dir_path = dir_path or os.path.join(os.getcwd(), "tests", call_type)
api_files = utils.load_folder_files(dir_path)
test_def_dict = {}
for test_file in api_files:
testset = load_testcases_by_path(test_file)
if not testset:
continue
suite = testset[0]
if call_type == "api":
test_dict = suite["api"]
elif call_type == "suite":
if "def" not in suite["config"]:
continue
call_func = suite["config"]["def"]
function_meta = parse_function(call_func)
suite["function_meta"] = function_meta
test_dict = {
function_meta["func_name"]: suite
}
test_def_dict.update(test_dict)
return test_def_dict
def substitute_variables_with_mapping(content, mapping): def substitute_variables_with_mapping(content, mapping):
""" substitute variables in content with mapping """ substitute variables in content with mapping
e.g. e.g.

View File

@@ -450,19 +450,20 @@ class TestcaseParserUnittest(unittest.TestCase):
self.assertFalse(result["request"]["data"]["false"]) self.assertFalse(result["request"]["data"]["false"])
self.assertEqual("", result["request"]["data"]["empty_str"]) self.assertEqual("", result["request"]["data"]["empty_str"])
def test_load_api_definition(self): def test_load_test_dependencies(self):
api_dir_dict = testcase.load_test_definition("api") testcase.test_def_overall_dict = {}
self.assertIn("get_token", api_dir_dict) testcase.load_test_dependencies()
self.assertEqual("/api/get-token", api_dir_dict["get_token"]["request"]["url"]) self.assertTrue(testcase.test_def_overall_dict["loaded"])
self.assertIn("$user_agent", api_dir_dict["get_token"]["function_meta"]["args"]) api_dict = testcase.test_def_overall_dict["api"]
self.assertIn("create_user", api_dir_dict) self.assertIn("get_token", api_dict)
self.assertEqual("/api/get-token", api_dict["get_token"]["request"]["url"])
self.assertIn("$user_agent", api_dict["get_token"]["function_meta"]["args"])
self.assertIn("create_user", api_dict)
def test_get_api_definition(self): def test_get_api_definition(self):
path = os.path.join( api_info = testcase.get_test_definition("get_token", "api")
os.getcwd(), 'tests/data')
api_info = testcase.get_test_definition("get_token", "api", path)
self.assertEqual("/api/get-token", api_info["request"]["url"]) self.assertEqual("/api/get-token", api_info["request"]["url"])
self.assertIn("get_token", testcase.test_def_overall_dict["api"]) self.assertIn("get_token", testcase.test_def_overall_dict["api"])
with self.assertRaises(ApiNotFound): with self.assertRaises(ApiNotFound):
testcase.get_test_definition("api_not_exist", "api", path) testcase.get_test_definition("api_not_exist", "api")