change: make converted referenced pytest files always relative to project RootDir

This commit is contained in:
debugtalk
2020-06-20 23:53:45 +08:00
parent 4f405d1620
commit 18e9b772fd
15 changed files with 132 additions and 193 deletions

View File

@@ -1,7 +1,7 @@
import os
import string
import subprocess
import sys
from shutil import copyfile
from typing import Text, List, Tuple, Dict, Set, NoReturn
import jinja2
@@ -21,9 +21,10 @@ from httprunner.loader import (
load_testcase,
load_testsuite,
load_project_meta,
convert_relative_project_root_dir,
)
from httprunner.response import uniform_validator
from httprunner.utils import ensure_file_abs_path_valid, override_config_variables
from httprunner.utils import override_config_variables
""" cache converted pytest files, avoid duplicate making
"""
@@ -36,11 +37,15 @@ pytest_files_run_set: Set = set()
__TEMPLATE__ = jinja2.Template(
"""# NOTE: Generated By HttpRunner v{{ version }}
# FROM: {{ testcase_path }}
{% if imports_list %}
import os
{% if imports_list and diff_levels > 0 %}
import sys
from pathlib import Path
sys.path.insert(0, os.getcwd())
sys.path.insert(0, str(Path(__file__)
{% for _ in range(diff_levels) %}
.parent
{% endfor %}
))
{% endif %}
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
{% for import_str in imports_list %}
@@ -86,44 +91,45 @@ def __ensure_absolute(path: Text) -> Text:
return absolute_path
def __convert_relative_current_working_dir(abs_path: Text) -> Text:
""" convert absolute path to relative path, based on os.getcwd()
def ensure_file_abs_path_valid(file_abs_path: Text) -> Text:
""" ensure file path valid for pytest, handle cases when directory name includes dot/hyphen/space
Args:
abs_path: absolute path
file_abs_path: absolute file path
Returns: relative path based on os.getcwd()
Returns:
ensured valid absolute file path
"""
cwd = os.getcwd()
if not abs_path.startswith(cwd):
raise exceptions.ParamsError(
f"failed to convert absolute path to relative path based on os.getcwd()\n"
f"abs_path: {abs_path}\n"
f"os.getcwd(): {cwd}"
)
project_meta = load_project_meta(file_abs_path)
raw_abs_file_name, file_suffix = os.path.splitext(file_abs_path)
file_suffix = file_suffix.lower()
return abs_path[len(cwd) + 1 :]
raw_file_relative_name = convert_relative_project_root_dir(raw_abs_file_name)
if raw_file_relative_name == "":
return file_abs_path
path_names = []
for name in raw_file_relative_name.rstrip(os.sep).split(os.sep):
def __convert_relative_project_root_dir(abs_path: Text) -> Text:
""" convert absolute path to relative path, based on project_meta.RootDir
if name[0] in string.digits:
# ensure file name not startswith digit
# 19 => T19, 2C => T2C
name = f"T{name}"
Args:
abs_path: absolute path
if name.startswith("."):
# avoid ".csv" been converted to "_csv"
pass
else:
# handle cases when directory name includes dot/hyphen/space
name = name.replace(" ", "_").replace(".", "_").replace("-", "_")
Returns: relative path based on project_meta.RootDir
path_names.append(name)
"""
project_meta = load_project_meta(abs_path)
if not abs_path.startswith(project_meta.RootDir):
raise exceptions.ParamsError(
f"failed to convert absolute path to relative path based on project_meta.RootDir\n"
f"abs_path: {abs_path}\n"
f"project_meta.RootDir: {project_meta.RootDir}"
)
return abs_path[len(project_meta.RootDir) + 1 :]
new_file_path = os.path.join(
project_meta.RootDir, f"{os.sep.join(path_names)}{file_suffix}"
)
return new_file_path
def __ensure_testcase_module(path: Text) -> NoReturn:
@@ -137,31 +143,6 @@ def __ensure_testcase_module(path: Text) -> NoReturn:
f.write("# NOTICE: Generated By HttpRunner. DO NOT EDIT!\n")
def __ensure_project_meta_files(tests_path: Text) -> NoReturn:
""" ensure project meta files exist in generated pytest folder files
include debugtalk.py and .env
"""
project_meta = load_project_meta(tests_path)
# handle cases when generated pytest directory are different from original yaml/json testcases
debugtalk_path = project_meta.debugtalk_path
if debugtalk_path:
debugtalk_new_path = ensure_file_abs_path_valid(debugtalk_path)
if debugtalk_new_path != debugtalk_path:
logger.info(f"copy debugtalk.py to {debugtalk_new_path}")
copyfile(debugtalk_path, debugtalk_new_path)
global pytest_files_made_cache_mapping
pytest_files_made_cache_mapping[debugtalk_new_path] = ""
dot_csv_path = project_meta.dot_env_path
if dot_csv_path:
dot_csv_new_path = ensure_file_abs_path_valid(dot_csv_path)
if dot_csv_new_path != dot_csv_path:
logger.info(f"copy .env to {dot_csv_new_path}")
copyfile(dot_csv_path, dot_csv_new_path)
def convert_testcase_path(testcase_abs_path: Text) -> Tuple[Text, Text]:
"""convert single YAML/JSON testcase path to python file"""
testcase_new_path = ensure_file_abs_path_valid(testcase_abs_path)
@@ -358,7 +339,7 @@ def make_testcase(testcase: Dict, dir_path: Text = None) -> Text:
return testcase_python_abs_path
config = testcase["config"]
config["path"] = __convert_relative_project_root_dir(testcase_python_abs_path)
config["path"] = convert_relative_project_root_dir(testcase_python_abs_path)
config["variables"] = convert_variables(
config.get("variables", {}), testcase_abs_path
)
@@ -388,7 +369,7 @@ def make_testcase(testcase: Dict, dir_path: Text = None) -> Text:
teststep["testcase"] = ref_testcase_cls_name
# prepare import ref testcase
ref_testcase_python_relative_path = __convert_relative_current_working_dir(
ref_testcase_python_relative_path = convert_relative_project_root_dir(
ref_testcase_python_abs_path
)
ref_module_name, _ = os.path.splitext(ref_testcase_python_relative_path)
@@ -397,9 +378,14 @@ def make_testcase(testcase: Dict, dir_path: Text = None) -> Text:
f"from {ref_module_name} import TestCase{ref_testcase_cls_name} as {ref_testcase_cls_name}"
)
testcase_path = convert_relative_project_root_dir(testcase_abs_path)
# current file compared to ProjectRootDir
diff_levels = len(testcase_path.split(os.sep))
data = {
"version": __version__,
"testcase_path": __convert_relative_project_root_dir(testcase_abs_path),
"testcase_path": testcase_path,
"diff_levels": diff_levels,
"class_name": f"TestCase{testcase_cls_name}",
"imports_list": imports_list,
"config_chain_style": make_config_chain_style(config),
@@ -564,8 +550,6 @@ def main_make(tests_paths: List[Text]) -> List[Text]:
logger.error(ex)
sys.exit(1)
__ensure_project_meta_files(tests_path)
# format pytest files
pytest_files_format_list = pytest_files_made_cache_mapping.keys()
format_pytest_with_black(*pytest_files_format_list)