From 6c29ea3554d52c0c27a620ccdf06621883da63e1 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Thu, 14 May 2020 23:21:15 +0800 Subject: [PATCH] feat: run test with reference testcase --- httprunner/make.py | 2 +- httprunner/new_loader.py | 16 +++++++++------- httprunner/runner.py | 32 ++++++++++++++++++++++---------- httprunner/schema.py | 2 +- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/httprunner/make.py b/httprunner/make.py index 7d7efe12..02564640 100644 --- a/httprunner/make.py +++ b/httprunner/make.py @@ -29,7 +29,7 @@ class {{ class_name }}(unittest.TestCase): def make_testcase(testcase_path: str) -> str: - testcase = load_testcase_file(testcase_path) + testcase, _ = load_testcase_file(testcase_path) template = jinja2.Template(__TMPL__) raw_file_name, _ = os.path.splitext(os.path.basename(testcase_path)) diff --git a/httprunner/new_loader.py b/httprunner/new_loader.py index b42b8395..d58f8ad8 100644 --- a/httprunner/new_loader.py +++ b/httprunner/new_loader.py @@ -4,13 +4,14 @@ import json import os import sys import types +from typing import Tuple, Dict import yaml from loguru import logger from httprunner import builtin, utils from httprunner import exceptions -from httprunner.schema import TestCase +from httprunner.schema import TestCase, ProjectMeta try: # PyYAML version >= 5.1 @@ -47,7 +48,7 @@ def _load_json_file(json_file): return json_content -def load_testcase_file(testcase_file): +def load_testcase_file(testcase_file) -> Tuple[Dict, TestCase]: """load testcase file and validate with pydantic model""" file_suffix = os.path.splitext(testcase_file)[1].lower() if file_suffix == ".json": @@ -61,9 +62,10 @@ def load_testcase_file(testcase_file): ) # validate with pydantic TestCase model - TestCase.parse_obj(testcase_content) + testcase_obj = TestCase.parse_obj(testcase_content) + testcase_obj.config.path = testcase_file - return testcase_content + return testcase_content, testcase_obj def load_dot_env_file(dot_env_path): @@ -302,7 +304,7 @@ def load_debugtalk_functions(): return load_module_functions(imported_module) -def load_project_data(test_path: str, dot_env_path: str = None): +def load_project_data(test_path: str, dot_env_path: str = None) -> ProjectMeta: """ load api, testcases, .env, debugtalk.py functions. api/testcases folder is relative to project_working_directory @@ -311,7 +313,7 @@ def load_project_data(test_path: str, dot_env_path: str = None): dot_env_path (str): specified .env file path Returns: - dict: project loaded api/testcases definitions, + project loaded api/testcases definitions, environments and debugtalk.py functions. """ @@ -341,4 +343,4 @@ def load_project_data(test_path: str, dot_env_path: str = None): len(project_working_directory) + 1 : ] - return project_meta + return ProjectMeta.parse_obj(project_meta) diff --git a/httprunner/runner.py b/httprunner/runner.py index bbeee279..ceaf2f42 100644 --- a/httprunner/runner.py +++ b/httprunner/runner.py @@ -1,3 +1,4 @@ +import os from typing import List, Dict from loguru import logger @@ -5,7 +6,7 @@ from loguru import logger from httprunner import utils, exceptions from httprunner.client import HttpSession from httprunner.exceptions import ValidationFailure, ParamsError -from httprunner.new_loader import load_project_data +from httprunner.new_loader import load_project_data, load_testcase_file from httprunner.parser import build_url, parse_data, parse_variables_mapping from httprunner.response import ResponseObject from httprunner.schema import ( @@ -17,8 +18,15 @@ from httprunner.schema import ( class TestCaseRunner(object): + def __init__( + self, + config: TestsConfig, + teststeps: List[TestStep], + session: HttpSession = None, + ): + if not config.path: + raise exceptions.ParamsError("config path missed!") - def __init__(self, config: TestsConfig, teststeps: List[TestStep], session: HttpSession = None): self.config = config self.teststeps = teststeps self.session = session @@ -27,6 +35,9 @@ class TestCaseRunner(object): self.session_variables: Dict = {} self.success: bool = True # indicate testcase execution result + self.project_data = load_project_data(self.config.path) + self.config.functions = self.project_data.functions + def with_variables(self, **variables: VariablesMapping) -> "TestCaseRunner": self.config.variables.update(variables) return self @@ -109,8 +120,15 @@ class TestCaseRunner(object): """run teststep: referenced testcase""" step_data = StepData(name=step.name) step_variables = step.variables - testcase: TestCaseRunner = step.testcase() # TODO: fix - case_result = testcase.with_variables(**step_variables).run() + + ref_testcase_path = os.path.join(self.project_data.PWD, step.testcase) + _, testcase_obj = load_testcase_file(ref_testcase_path) + + case_result = ( + TestCaseRunner(testcase_obj.config, testcase_obj.teststeps, self.session) + .with_variables(**step_variables) + .run() + ) step_data.data = case_result.step_datas # list of step data step_data.export = case_result.get_export_variables() step_data.success = case_result.success @@ -136,12 +154,6 @@ class TestCaseRunner(object): def run(self): """main entrance""" - if not self.config.path: - raise exceptions.ParamsError("config path missed!") - - project_data = load_project_data(self.config.path) - self.config.functions = project_data["functions"] - self.step_datas.clear() self.session_variables.clear() for step in self.teststeps: diff --git a/httprunner/schema.py b/httprunner/schema.py index 0130f769..585e6c42 100644 --- a/httprunner/schema.py +++ b/httprunner/schema.py @@ -61,7 +61,7 @@ class Request(BaseModel): class TestStep(BaseModel): name: Name request: Request = None - testcase: Union[Text, Callable] = None + testcase: Text = "" variables: VariablesMapping = {} extract: Dict[Text, Text] = {} validators: Validators = Field([], alias="validate")