mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-04 23:16:57 +08:00
refactor: use step export to export session variables from referenced testcase
This commit is contained in:
@@ -11,7 +11,7 @@ teststeps:
|
|||||||
variables:
|
variables:
|
||||||
foo1: override_bar1
|
foo1: override_bar1
|
||||||
testcase: request_methods/request_with_functions.yml
|
testcase: request_methods/request_with_functions.yml
|
||||||
extract:
|
export:
|
||||||
- session_foo2
|
- session_foo2
|
||||||
-
|
-
|
||||||
name: post form data
|
name: post form data
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class TestCaseRequestWithTestcaseReference(HttpRunner):
|
|||||||
RunTestCase("request with functions")
|
RunTestCase("request with functions")
|
||||||
.with_variables(**{"foo1": "override_bar1"})
|
.with_variables(**{"foo1": "override_bar1"})
|
||||||
.call(RequestWithFunctions)
|
.call(RequestWithFunctions)
|
||||||
.extract(*["session_foo2"])
|
.export(*["session_foo2"])
|
||||||
),
|
),
|
||||||
Step(
|
Step(
|
||||||
RunRequest("post form data")
|
RunRequest("post form data")
|
||||||
|
|||||||
@@ -133,10 +133,10 @@ def ensure_step_attachment(step: Dict) -> Dict:
|
|||||||
test_dict["teardown_hooks"] = step["teardown_hooks"]
|
test_dict["teardown_hooks"] = step["teardown_hooks"]
|
||||||
|
|
||||||
if "extract" in step:
|
if "extract" in step:
|
||||||
if step.get("request"):
|
test_dict["extract"] = convert_extractors(step["extract"])
|
||||||
test_dict["extract"] = convert_extractors(step["extract"])
|
|
||||||
elif step.get("testcase"):
|
if "export" in step:
|
||||||
test_dict["extract"] = step["extract"]
|
test_dict["export"] = step["export"]
|
||||||
|
|
||||||
if "validate" in step:
|
if "validate" in step:
|
||||||
test_dict["validate"] = convert_validators(step["validate"])
|
test_dict["validate"] = convert_validators(step["validate"])
|
||||||
@@ -167,8 +167,6 @@ def ensure_testcase_v3(test_content: Dict) -> Dict:
|
|||||||
for step in test_content["teststeps"]:
|
for step in test_content["teststeps"]:
|
||||||
teststep = {}
|
teststep = {}
|
||||||
|
|
||||||
teststep.update(ensure_step_attachment(step))
|
|
||||||
|
|
||||||
if "request" in step:
|
if "request" in step:
|
||||||
teststep["request"] = step.pop("request")
|
teststep["request"] = step.pop("request")
|
||||||
elif "api" in step:
|
elif "api" in step:
|
||||||
@@ -176,6 +174,8 @@ def ensure_testcase_v3(test_content: Dict) -> Dict:
|
|||||||
elif "testcase" in step:
|
elif "testcase" in step:
|
||||||
teststep["testcase"] = step.pop("testcase")
|
teststep["testcase"] = step.pop("testcase")
|
||||||
|
|
||||||
|
teststep.update(ensure_step_attachment(step))
|
||||||
|
|
||||||
teststep = sort_step_by_custom_order(teststep)
|
teststep = sort_step_by_custom_order(teststep)
|
||||||
v3_content["teststeps"].append(teststep)
|
v3_content["teststeps"].append(teststep)
|
||||||
|
|
||||||
|
|||||||
+11
-12
@@ -220,18 +220,16 @@ def make_teststep_chain_style(teststep: Dict) -> Text:
|
|||||||
call_ref_testcase = f".call({testcase})"
|
call_ref_testcase = f".call({testcase})"
|
||||||
step_info += call_ref_testcase
|
step_info += call_ref_testcase
|
||||||
|
|
||||||
extract_info = teststep.get("extract")
|
if "extract" in teststep:
|
||||||
if extract_info:
|
# request step
|
||||||
if isinstance(extract_info, Dict):
|
step_info += ".extract()"
|
||||||
# request step
|
for extract_name, extract_path in teststep["extract"].items():
|
||||||
step_info += ".extract()"
|
step_info += f'.with_jmespath("{extract_path}", "{extract_name}")'
|
||||||
for extract_name, extract_path in extract_info.items():
|
|
||||||
step_info += f'.with_jmespath("{extract_path}", "{extract_name}")'
|
if "export" in teststep:
|
||||||
elif isinstance(extract_info, List):
|
# reference testcase step
|
||||||
# reference testcase step
|
export: List[Text] = teststep["export"]
|
||||||
step_info += f".extract(*{extract_info})"
|
step_info += f".export(*{export})"
|
||||||
else:
|
|
||||||
raise exceptions.TestCaseFormatError(f"Invalid extract: {extract_info}")
|
|
||||||
|
|
||||||
if "validate" in teststep:
|
if "validate" in teststep:
|
||||||
step_info += ".validate()"
|
step_info += ".validate()"
|
||||||
@@ -455,6 +453,7 @@ def main_make(tests_paths: List[Text]) -> List[Text]:
|
|||||||
|
|
||||||
pytest_files_set.update(make_files_cache_set)
|
pytest_files_set.update(make_files_cache_set)
|
||||||
pytest_files_list = list(pytest_files_set)
|
pytest_files_list = list(pytest_files_set)
|
||||||
|
# TODO: format referenced testcase
|
||||||
format_pytest_with_black(*pytest_files_list)
|
format_pytest_with_black(*pytest_files_list)
|
||||||
return pytest_files_list
|
return pytest_files_list
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,10 @@ class TStep(BaseModel):
|
|||||||
variables: VariablesMapping = {}
|
variables: VariablesMapping = {}
|
||||||
setup_hooks: Hook = []
|
setup_hooks: Hook = []
|
||||||
teardown_hooks: Hook = []
|
teardown_hooks: Hook = []
|
||||||
extract: Union[Dict[Text, Text], List[Text]] = {}
|
# used to extract request's response field
|
||||||
|
extract: Dict[Text, Text] = {}
|
||||||
|
# used to export session variables from referenced testcase
|
||||||
|
export: List[Text] = []
|
||||||
validators: Validators = Field([], alias="validate")
|
validators: Validators = Field([], alias="validate")
|
||||||
validate_script: List[Text] = []
|
validate_script: List[Text] = []
|
||||||
|
|
||||||
|
|||||||
+14
-11
@@ -43,10 +43,10 @@ class HttpRunner(object):
|
|||||||
__teststeps: List[TStep]
|
__teststeps: List[TStep]
|
||||||
__project_meta: ProjectMeta = None
|
__project_meta: ProjectMeta = None
|
||||||
__case_id: Text = ""
|
__case_id: Text = ""
|
||||||
|
__export: List[Text] = []
|
||||||
__step_datas: List[StepData] = None
|
__step_datas: List[StepData] = None
|
||||||
__session: HttpSession = None
|
__session: HttpSession = None
|
||||||
__session_variables: VariablesMapping = {}
|
__session_variables: VariablesMapping = {}
|
||||||
__export_variables: VariablesMapping = {}
|
|
||||||
# time
|
# time
|
||||||
__start_at: float = 0
|
__start_at: float = 0
|
||||||
__duration: float = 0
|
__duration: float = 0
|
||||||
@@ -82,6 +82,10 @@ class HttpRunner(object):
|
|||||||
self.__session_variables = variables
|
self.__session_variables = variables
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def with_export(self, export: List[Text]) -> "HttpRunner":
|
||||||
|
self.__export = export
|
||||||
|
return self
|
||||||
|
|
||||||
def __run_step_request(self, step: TStep) -> StepData:
|
def __run_step_request(self, step: TStep) -> StepData:
|
||||||
"""run teststep: request"""
|
"""run teststep: request"""
|
||||||
step_data = StepData(name=step.name)
|
step_data = StepData(name=step.name)
|
||||||
@@ -166,6 +170,7 @@ class HttpRunner(object):
|
|||||||
"""run teststep: referenced testcase"""
|
"""run teststep: referenced testcase"""
|
||||||
step_data = StepData(name=step.name)
|
step_data = StepData(name=step.name)
|
||||||
step_variables = step.variables
|
step_variables = step.variables
|
||||||
|
step_export = step.export
|
||||||
|
|
||||||
if hasattr(step.testcase, "config") and hasattr(step.testcase, "teststeps"):
|
if hasattr(step.testcase, "config") and hasattr(step.testcase, "teststeps"):
|
||||||
testcase_cls = step.testcase
|
testcase_cls = step.testcase
|
||||||
@@ -174,6 +179,7 @@ class HttpRunner(object):
|
|||||||
.with_session(self.__session)
|
.with_session(self.__session)
|
||||||
.with_case_id(self.__case_id)
|
.with_case_id(self.__case_id)
|
||||||
.with_variables(step_variables)
|
.with_variables(step_variables)
|
||||||
|
.with_export(step_export)
|
||||||
.run()
|
.run()
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -188,6 +194,7 @@ class HttpRunner(object):
|
|||||||
.with_session(self.__session)
|
.with_session(self.__session)
|
||||||
.with_case_id(self.__case_id)
|
.with_case_id(self.__case_id)
|
||||||
.with_variables(step_variables)
|
.with_variables(step_variables)
|
||||||
|
.with_export(step_export)
|
||||||
.run_path(ref_testcase_path)
|
.run_path(ref_testcase_path)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -201,6 +208,9 @@ class HttpRunner(object):
|
|||||||
step_data.success = case_result.success
|
step_data.success = case_result.success
|
||||||
self.success &= case_result.success
|
self.success &= case_result.success
|
||||||
|
|
||||||
|
if step_data.export:
|
||||||
|
logger.info(f"export variables: {step_data.export}")
|
||||||
|
|
||||||
return step_data
|
return step_data
|
||||||
|
|
||||||
def __run_step(self, step: TStep) -> Dict:
|
def __run_step(self, step: TStep) -> Dict:
|
||||||
@@ -252,7 +262,6 @@ class HttpRunner(object):
|
|||||||
self.__step_datas: List[StepData] = []
|
self.__step_datas: List[StepData] = []
|
||||||
self.__session = self.__session or HttpSession()
|
self.__session = self.__session or HttpSession()
|
||||||
self.__session_variables = {}
|
self.__session_variables = {}
|
||||||
self.__export_variables = {}
|
|
||||||
|
|
||||||
# run teststeps
|
# run teststeps
|
||||||
for step in self.__teststeps:
|
for step in self.__teststeps:
|
||||||
@@ -274,11 +283,6 @@ class HttpRunner(object):
|
|||||||
self.__session_variables.update(extract_mapping)
|
self.__session_variables.update(extract_mapping)
|
||||||
|
|
||||||
self.__duration = time.time() - self.__start_at
|
self.__duration = time.time() - self.__start_at
|
||||||
|
|
||||||
self.__export_variables = self.get_export_variables()
|
|
||||||
if self.__export_variables:
|
|
||||||
logger.info(f"export variables: {self.__export_variables}")
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def run_path(self, path: Text) -> "HttpRunner":
|
def run_path(self, path: Text) -> "HttpRunner":
|
||||||
@@ -303,11 +307,10 @@ class HttpRunner(object):
|
|||||||
return self.__step_datas
|
return self.__step_datas
|
||||||
|
|
||||||
def get_export_variables(self) -> Dict:
|
def get_export_variables(self) -> Dict:
|
||||||
if self.__export_variables:
|
# override testcase export vars with step export
|
||||||
return self.__export_variables
|
export_var_names = self.__export or self.__config.export
|
||||||
|
|
||||||
export_vars_mapping = {}
|
export_vars_mapping = {}
|
||||||
for var_name in self.__config.export:
|
for var_name in export_var_names:
|
||||||
if var_name not in self.__session_variables:
|
if var_name not in self.__session_variables:
|
||||||
raise ParamsError(
|
raise ParamsError(
|
||||||
f"failed to export variable {var_name} from session variables {self.__session_variables}"
|
f"failed to export variable {var_name} from session variables {self.__session_variables}"
|
||||||
|
|||||||
@@ -298,10 +298,9 @@ class RunRequest(object):
|
|||||||
class StepRefCase(object):
|
class StepRefCase(object):
|
||||||
def __init__(self, step: TStep):
|
def __init__(self, step: TStep):
|
||||||
self.__t_step = step
|
self.__t_step = step
|
||||||
self.__t_step.extract = []
|
|
||||||
|
|
||||||
def extract(self, *var_name: Text) -> "StepRefCase":
|
def export(self, *var_name: Text) -> "StepRefCase":
|
||||||
self.__t_step.extract.extend(var_name)
|
self.__t_step.export.extend(var_name)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def perform(self) -> TStep:
|
def perform(self) -> TStep:
|
||||||
|
|||||||
Reference in New Issue
Block a user