Files
httprunner/httprunner/ext/make/__init__.py
2020-05-15 18:30:06 +08:00

129 lines
3.7 KiB
Python

import os
import subprocess
from typing import Union, Text, List
import jinja2
from loguru import logger
from httprunner import exceptions
from httprunner.exceptions import TestCaseFormatError
from httprunner.loader import load_testcase_file, load_folder_files
__TMPL__ = """# NOTICE: Generated By HttpRunner. DO'NOT EDIT!
from httprunner import HttpRunner, TConfig, TStep, TestCase
class {{ class_name }}(TestCase):
config = TConfig(**{{ config }})
teststeps = [
{% for teststep in teststeps %}
TStep(**{{ teststep }}),
{% endfor %}
]
def test_start(self):
HttpRunner(self.config, self.teststeps).run()
"""
def make_testcase(testcase_path: str) -> Union[str, None]:
logger.info(f"start to make testcase: {testcase_path}")
try:
testcase, _ = load_testcase_file(testcase_path)
except TestCaseFormatError:
return None
template = jinja2.Template(__TMPL__)
raw_file_name, _ = os.path.splitext(os.path.basename(testcase_path))
# convert title case, e.g. request_with_variables => RequestWithVariables
name_in_title_case = raw_file_name.title().replace("_", "")
testcase_dir = os.path.dirname(testcase_path)
testcase_python_path = os.path.join(testcase_dir, f"{raw_file_name}_test.py")
config = testcase["config"]
config["path"] = testcase_python_path
data = {
"class_name": f"TestCase{name_in_title_case}",
"config": config,
"teststeps": testcase["teststeps"],
}
content = template.render(data)
with open(testcase_python_path, "w") as f:
f.write(content)
logger.info(f"generated testcase: {testcase_python_path}")
return testcase_python_path
def convert_testcase_path(testcase_path: Text) -> Text:
"""convert single YAML/JSON testcase path to python file"""
if os.path.isdir(testcase_path):
# folder does not need to convert
return testcase_path
file_suffix = os.path.splitext(testcase_path)[1].lower()
if file_suffix == ".json":
return testcase_path.replace(".json", "_test.py")
elif file_suffix == ".yaml":
return testcase_path.replace(".yaml", "_test.py")
elif file_suffix == ".yml":
return testcase_path.replace(".yml", "_test.py")
else:
raise exceptions.ParamsError("")
def format_with_black(tests_path: Text):
logger.info("format testcases with black ...")
tests_path = convert_testcase_path(tests_path)
try:
subprocess.run(["black", tests_path])
except subprocess.CalledProcessError as ex:
logger.error(ex)
def make(tests_path: Text) -> List:
testcases = []
if os.path.isdir(tests_path):
files_list = load_folder_files(tests_path)
testcases.extend(files_list)
elif os.path.isfile(tests_path):
testcases.append(tests_path)
else:
raise exceptions.TestcaseNotFound(f"Invalid tests path: {tests_path}")
testcase_path_list = []
for testcase_path in testcases:
testcase_path = make_testcase(testcase_path)
if not testcase_path:
continue
testcase_path_list.append(testcase_path)
format_with_black(tests_path)
return testcase_path_list
def main_make(tests_paths: List[Text]) -> List:
testcase_path_list = []
for tests_path in tests_paths:
testcase_path_list.extend(make(tests_path))
return testcase_path_list
def init_make_parser(subparsers):
""" make testcases: parse command line options and run commands.
"""
parser = subparsers.add_parser(
"make", help="Convert YAML/JSON testcases to Python unittests.",
)
parser.add_argument(
"testcase_path", nargs="*", help="Specify YAML/JSON testcase file/folder path"
)
return parser