change: remove testsuite

This commit is contained in:
debugtalk
2022-04-23 15:04:35 +08:00
parent 24fcdfb418
commit 74299a5a5c
4 changed files with 71 additions and 191 deletions
+4 -19
View File
@@ -11,14 +11,13 @@ from loguru import logger
from pydantic import ValidationError from pydantic import ValidationError
from httprunner import builtin, exceptions, utils from httprunner import builtin, exceptions, utils
from httprunner.models import ProjectMeta, TestCase, TestSuite from httprunner.models import ProjectMeta, TestCase
project_meta: Union[ProjectMeta, None] = None project_meta: Union[ProjectMeta, None] = None
def _load_yaml_file(yaml_file: Text) -> Dict: def _load_yaml_file(yaml_file: Text) -> Dict:
""" load yaml file and check file content format """load yaml file and check file content format"""
"""
with open(yaml_file, mode="rb") as stream: with open(yaml_file, mode="rb") as stream:
try: try:
yaml_content = yaml.load(stream, Loader=yaml.FullLoader) yaml_content = yaml.load(stream, Loader=yaml.FullLoader)
@@ -31,8 +30,7 @@ def _load_yaml_file(yaml_file: Text) -> Dict:
def _load_json_file(json_file: Text) -> Dict: def _load_json_file(json_file: Text) -> Dict:
""" load json file and check file content format """load json file and check file content format"""
"""
with open(json_file, mode="rb") as data_file: with open(json_file, mode="rb") as data_file:
try: try:
json_content = json.load(data_file) json_content = json.load(data_file)
@@ -81,18 +79,6 @@ def load_testcase_file(testcase_file: Text) -> TestCase:
return testcase_obj return testcase_obj
def load_testsuite(testsuite: Dict) -> TestSuite:
path = testsuite["config"]["path"]
try:
# validate with pydantic TestCase model
testsuite_obj = TestSuite.parse_obj(testsuite)
except ValidationError as ex:
err_msg = f"TestSuite ValidationError:\nfile: {path}\nerror: {ex}"
raise exceptions.TestSuiteFormatError(err_msg)
return testsuite_obj
def load_dot_env_file(dot_env_path: Text) -> Dict: def load_dot_env_file(dot_env_path: Text) -> Dict:
"""load .env file. """load .env file.
@@ -251,8 +237,7 @@ def load_module_functions(module) -> Dict[Text, Callable]:
def load_builtin_functions() -> Dict[Text, Callable]: def load_builtin_functions() -> Dict[Text, Callable]:
""" load builtin module functions """load builtin module functions"""
"""
return load_module_functions(builtin) return load_module_functions(builtin)
+25 -86
View File
@@ -8,14 +8,21 @@ import jinja2
from loguru import logger from loguru import logger
from httprunner import __version__, exceptions from httprunner import __version__, exceptions
from httprunner.compat import (convert_variables, ensure_path_sep, from httprunner.compat import (
ensure_testcase_v3, ensure_testcase_v3_api) convert_variables,
from httprunner.loader import (convert_relative_project_root_dir, ensure_path_sep,
load_folder_files, load_project_meta, ensure_testcase_v3,
load_test_file, load_testcase, load_testsuite) ensure_testcase_v3_api,
)
from httprunner.loader import (
convert_relative_project_root_dir,
load_folder_files,
load_project_meta,
load_test_file,
load_testcase,
)
from httprunner.response import uniform_validator from httprunner.response import uniform_validator
from httprunner.utils import (ga_client, is_support_multiprocessing, from httprunner.utils import ga_client, is_support_multiprocessing
merge_variables)
""" cache converted pytest files, avoid duplicate making """ cache converted pytest files, avoid duplicate making
""" """
@@ -133,8 +140,7 @@ def ensure_file_abs_path_valid(file_abs_path: Text) -> Text:
def __ensure_testcase_module(path: Text): def __ensure_testcase_module(path: Text):
""" ensure pytest files are in python module, generate __init__.py on demand """ensure pytest files are in python module, generate __init__.py on demand"""
"""
init_file = os.path.join(os.path.dirname(path), "__init__.py") init_file = os.path.join(os.path.dirname(path), "__init__.py")
if os.path.isfile(init_file): if os.path.isfile(init_file):
return return
@@ -431,61 +437,8 @@ def make_testcase(testcase: Dict, dir_path: Text = None) -> Text:
return testcase_python_abs_path return testcase_python_abs_path
def make_testsuite(testsuite: Dict):
"""convert valid testsuite dict to pytest folder with testcases"""
# validate testsuite format
load_testsuite(testsuite)
testsuite_config = testsuite["config"]
testsuite_path = testsuite_config["path"]
testsuite_variables = convert_variables(
testsuite_config.get("variables", {}), testsuite_path
)
logger.info(f"start to make testsuite: {testsuite_path}")
# create directory with testsuite file name, put its testcases under this directory
testsuite_path = ensure_file_abs_path_valid(testsuite_path)
testsuite_dir, file_suffix = os.path.splitext(testsuite_path)
# demo_testsuite.yml => demo_testsuite_yml
testsuite_dir = f"{testsuite_dir}_{file_suffix.lstrip('.')}"
for testcase in testsuite["testcases"]:
# get referenced testcase content
testcase_file = testcase["testcase"]
testcase_path = __ensure_absolute(testcase_file)
testcase_dict = load_test_file(testcase_path)
testcase_dict.setdefault("config", {})
testcase_dict["config"]["path"] = testcase_path
# override testcase name
testcase_dict["config"]["name"] = testcase["name"]
# override base_url
base_url = testsuite_config.get("base_url") or testcase.get("base_url")
if base_url:
testcase_dict["config"]["base_url"] = base_url
# override verify
if "verify" in testsuite_config:
testcase_dict["config"]["verify"] = testsuite_config["verify"]
# override variables
# testsuite testcase variables > testsuite config variables
testcase_variables = convert_variables(
testcase.get("variables", {}), testcase_path
)
testcase_variables = merge_variables(testcase_variables, testsuite_variables)
# testsuite testcase variables > testcase config variables
testcase_dict["config"]["variables"] = convert_variables(
testcase_dict["config"].get("variables", {}), testcase_path
)
testcase_dict["config"]["variables"].update(testcase_variables)
# make testcase
testcase_pytest_path = make_testcase(testcase_dict, testsuite_dir)
pytest_files_run_set.add(testcase_pytest_path)
def __make(tests_path: Text): def __make(tests_path: Text):
""" make testcase(s) with testcase/testsuite/folder absolute path """make testcase(s) with testcase/folder absolute path
generated pytest file path will be cached in pytest_files_made_cache_mapping generated pytest file path will be cached in pytest_files_made_cache_mapping
Args: Args:
@@ -526,13 +479,13 @@ def __make(tests_path: Text):
if "config" not in test_content: if "config" not in test_content:
logger.warning( logger.warning(
f"Invalid testcase/testsuite file: {test_file}\n" f"Invalid testcase file: {test_file}\n"
f"reason: missing config part." f"reason: missing config part."
) )
continue continue
elif not isinstance(test_content["config"], Dict): elif not isinstance(test_content["config"], Dict):
logger.warning( logger.warning(
f"Invalid testcase/testsuite file: {test_file}\n" f"Invalid testcase file: {test_file}\n"
f"reason: config should be dict type, got {test_content['config']}" f"reason: config should be dict type, got {test_content['config']}"
) )
continue continue
@@ -540,8 +493,11 @@ def __make(tests_path: Text):
# ensure path absolute # ensure path absolute
test_content.setdefault("config", {})["path"] = test_file test_content.setdefault("config", {})["path"] = test_file
# invalid format
if "teststeps" not in test_content:
logger.warning(f"Invalid testcase file: {test_file}")
# testcase # testcase
if "teststeps" in test_content:
try: try:
testcase_pytest_path = make_testcase(test_content) testcase_pytest_path = make_testcase(test_content)
pytest_files_run_set.add(testcase_pytest_path) pytest_files_run_set.add(testcase_pytest_path)
@@ -551,23 +507,6 @@ def __make(tests_path: Text):
) )
continue continue
# testsuite
elif "testcases" in test_content:
try:
make_testsuite(test_content)
except exceptions.TestSuiteFormatError as ex:
logger.warning(
f"Invalid testsuite file: {test_file}\n{type(ex).__name__}: {ex}"
)
continue
# invalid format
else:
logger.warning(
f"Invalid test file: {test_file}\n"
f"reason: file content is neither testcase nor testsuite"
)
def main_make(tests_paths: List[Text]) -> List[Text]: def main_make(tests_paths: List[Text]) -> List[Text]:
if not tests_paths: if not tests_paths:
@@ -594,10 +533,10 @@ def main_make(tests_paths: List[Text]) -> List[Text]:
def init_make_parser(subparsers): def init_make_parser(subparsers):
""" make testcases: parse command line options and run commands. """make testcases: parse command line options and run commands."""
"""
parser = subparsers.add_parser( parser = subparsers.add_parser(
"make", help="Convert YAML/JSON testcases to pytest cases.", "make",
help="Convert YAML/JSON testcases to pytest cases.",
) )
parser.add_argument( parser.add_argument(
"testcase_path", nargs="*", help="Specify YAML/JSON testcase file/folder path" "testcase_path", nargs="*", help="Specify YAML/JSON testcase file/folder path"
+13 -46
View File
@@ -73,7 +73,8 @@ from request_methods.request_with_functions_test import (
content, content,
) )
self.assertIn( self.assertIn(
".call(RequestWithFunctions)", content, ".call(RequestWithFunctions)",
content,
) )
def test_make_testcase_folder(self): def test_make_testcase_folder(self):
@@ -94,9 +95,7 @@ from request_methods.request_with_functions_test import (
def test_ensure_file_path_valid(self): def test_ensure_file_path_valid(self):
self.assertEqual( self.assertEqual(
ensure_file_abs_path_valid( ensure_file_abs_path_valid(os.path.join(self.data_dir, "a-b.c", "2 3.yml")),
os.path.join(self.data_dir, "a-b.c", "2 3.yml")
),
os.path.join(self.data_dir, "a_b_c", "T2_3.yml"), os.path.join(self.data_dir, "a_b_c", "T2_3.yml"),
) )
loader.project_meta = None loader.project_meta = None
@@ -113,67 +112,31 @@ from request_methods.request_with_functions_test import (
) )
loader.project_meta = None loader.project_meta = None
self.assertEqual( self.assertEqual(
ensure_file_abs_path_valid(os.getcwd()), os.getcwd(), ensure_file_abs_path_valid(os.getcwd()),
os.getcwd(),
) )
loader.project_meta = None loader.project_meta = None
self.assertEqual( self.assertEqual(
ensure_file_abs_path_valid( ensure_file_abs_path_valid(os.path.join(self.data_dir, ".csv")),
os.path.join(self.data_dir, ".csv")
),
os.path.join(self.data_dir, ".csv"), os.path.join(self.data_dir, ".csv"),
) )
def test_convert_testcase_path(self): def test_convert_testcase_path(self):
self.assertEqual( self.assertEqual(
convert_testcase_path( convert_testcase_path(os.path.join(self.data_dir, "a-b.c", "2 3.yml")),
os.path.join(self.data_dir, "a-b.c", "2 3.yml")
),
( (
os.path.join(self.data_dir, "a_b_c", "T2_3_test.py"), os.path.join(self.data_dir, "a_b_c", "T2_3_test.py"),
"T23", "T23",
), ),
) )
self.assertEqual( self.assertEqual(
convert_testcase_path( convert_testcase_path(os.path.join(self.data_dir, "a-b.c", "中文case.yml")),
os.path.join(self.data_dir, "a-b.c", "中文case.yml")
),
( (
os.path.join(self.data_dir, "a_b_c", "中文case_test.py"), os.path.join(self.data_dir, "a_b_c", "中文case_test.py"),
"中文Case", "中文Case",
), ),
) )
def test_make_testsuite(self):
path = ["examples/postman_echo/request_methods/demo_testsuite.yml"]
testcase_python_list = main_make(path)
self.assertEqual(len(testcase_python_list), 2)
self.assertIn(
os.path.join(
os.getcwd(),
os.path.join(
"examples",
"postman_echo",
"request_methods",
"demo_testsuite_yml",
"request_with_functions_test.py",
),
),
testcase_python_list,
)
self.assertIn(
os.path.join(
os.getcwd(),
os.path.join(
"examples",
"postman_echo",
"request_methods",
"demo_testsuite_yml",
"request_with_testcase_reference_test.py",
),
),
testcase_python_list,
)
def test_make_config_chain_style(self): def test_make_config_chain_style(self):
config = { config = {
"name": "request methods testcase: validate with functions", "name": "request methods testcase: validate with functions",
@@ -190,7 +153,11 @@ from request_methods.request_with_functions_test import (
def test_make_teststep_chain_style(self): def test_make_teststep_chain_style(self):
step = { step = {
"name": "get with params", "name": "get with params",
"variables": {"foo1": "bar1", "foo2": 123, "sum_v": "${sum_two(1, 2)}",}, "variables": {
"foo1": "bar1",
"foo2": 123,
"sum_v": "${sum_two(1, 2)}",
},
"request": { "request": {
"method": "GET", "method": "GET",
"url": "/get", "url": "/get",
+4 -15
View File
@@ -97,7 +97,9 @@ class ProjectMeta(BaseModel):
dot_env_path: Text = "" # .env file path dot_env_path: Text = "" # .env file path
functions: FunctionsMapping = {} # functions defined in debugtalk.py functions: FunctionsMapping = {} # functions defined in debugtalk.py
env: Env = {} env: Env = {}
RootDir: Text = os.getcwd() # project root directory (ensure absolute), the path debugtalk.py located RootDir: Text = (
os.getcwd()
) # project root directory (ensure absolute), the path debugtalk.py located
class TestsMapping(BaseModel): class TestsMapping(BaseModel):
@@ -169,7 +171,7 @@ class StepResult(BaseModel):
name: Text = "" # teststep name name: Text = "" # teststep name
step_type: Text = "" # teststep type, request or testcase step_type: Text = "" # teststep type, request or testcase
success: bool = False success: bool = False
data: Union[SessionData, List['StepResult']] = None data: Union[SessionData, List["StepResult"]] = None
elapsed: float = 0.0 # teststep elapsed time elapsed: float = 0.0 # teststep elapsed time
content_size: float = 0 # response content size content_size: float = 0 # response content size
export_vars: VariablesMapping = {} export_vars: VariablesMapping = {}
@@ -180,7 +182,6 @@ StepResult.update_forward_refs()
class IStep(object): class IStep(object):
def name(self) -> str: def name(self) -> str:
raise NotImplementedError raise NotImplementedError
@@ -211,18 +212,6 @@ class PlatformInfo(BaseModel):
platform: Text platform: Text
class TestCaseRef(BaseModel):
name: Text
base_url: Text = ""
testcase: Text
variables: VariablesMapping = {}
class TestSuite(BaseModel):
config: TConfig
testcases: List[TestCaseRef]
class Stat(BaseModel): class Stat(BaseModel):
total: int = 0 total: int = 0
success: int = 0 success: int = 0