mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-12 16:01:27 +08:00
feat: implement step setup/teardown hooks
This commit is contained in:
@@ -1,5 +1,11 @@
|
|||||||
# Release History
|
# Release History
|
||||||
|
|
||||||
|
## 3.0.10 (2020-06-07)
|
||||||
|
|
||||||
|
**Added**
|
||||||
|
|
||||||
|
- feat: implement step setup/teardown hooks
|
||||||
|
|
||||||
## 3.0.9 (2020-06-07)
|
## 3.0.9 (2020-06-07)
|
||||||
|
|
||||||
**Fixed**
|
**Fixed**
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ FunctionsMapping = Dict[Text, Callable]
|
|||||||
Headers = Dict[Text, Text]
|
Headers = Dict[Text, Text]
|
||||||
Cookies = Dict[Text, Text]
|
Cookies = Dict[Text, Text]
|
||||||
Verify = bool
|
Verify = bool
|
||||||
Hook = List[Text]
|
Hooks = Union[List[Text], Dict[Text, Text]]
|
||||||
Export = List[Text]
|
Export = List[Text]
|
||||||
Validators = List[Dict]
|
Validators = List[Dict]
|
||||||
Env = Dict[Text, Any]
|
Env = Dict[Text, Any]
|
||||||
@@ -37,8 +37,8 @@ class TConfig(BaseModel):
|
|||||||
base_url: BaseUrl = ""
|
base_url: BaseUrl = ""
|
||||||
# Text: prepare variables in debugtalk.py, ${gen_variables()}
|
# Text: prepare variables in debugtalk.py, ${gen_variables()}
|
||||||
variables: Union[VariablesMapping, Text] = {}
|
variables: Union[VariablesMapping, Text] = {}
|
||||||
setup_hooks: Hook = []
|
# setup_hooks: Hooks = []
|
||||||
teardown_hooks: Hook = []
|
# teardown_hooks: Hooks = []
|
||||||
export: Export = []
|
export: Export = []
|
||||||
path: Text = None
|
path: Text = None
|
||||||
|
|
||||||
@@ -64,8 +64,8 @@ class TStep(BaseModel):
|
|||||||
request: Union[TRequest, None] = None
|
request: Union[TRequest, None] = None
|
||||||
testcase: Union[Text, Callable, None] = None
|
testcase: Union[Text, Callable, None] = None
|
||||||
variables: VariablesMapping = {}
|
variables: VariablesMapping = {}
|
||||||
setup_hooks: Hook = []
|
setup_hooks: Hooks = []
|
||||||
teardown_hooks: Hook = []
|
teardown_hooks: Hooks = []
|
||||||
# used to extract request's response field
|
# used to extract request's response field
|
||||||
extract: VariablesMapping = {}
|
extract: VariablesMapping = {}
|
||||||
# used to export session variables from referenced testcase
|
# used to export session variables from referenced testcase
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import os
|
|||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import List, Dict, Text, NoReturn
|
from typing import List, Dict, Text, NoReturn, Union
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import allure
|
import allure
|
||||||
@@ -31,6 +31,7 @@ from httprunner.models import (
|
|||||||
TestCaseInOut,
|
TestCaseInOut,
|
||||||
ProjectMeta,
|
ProjectMeta,
|
||||||
TestCase,
|
TestCase,
|
||||||
|
Hooks,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -86,6 +87,50 @@ class HttpRunner(object):
|
|||||||
self.__export = export
|
self.__export = export
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def __call_hooks(
|
||||||
|
self, hooks: Hooks, step_variables: VariablesMapping, hook_type: Text,
|
||||||
|
) -> NoReturn:
|
||||||
|
""" call hook actions.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
hooks: each action in actions list maybe in two format.
|
||||||
|
|
||||||
|
format1 (dict): assignment, the value returned by hook function will be assigned to variable.
|
||||||
|
{"var": "${func()}"}
|
||||||
|
format2 (str): only call hook functions.
|
||||||
|
${func()}
|
||||||
|
|
||||||
|
step_variables: current step variables to call hook, include two special variables
|
||||||
|
|
||||||
|
request: parsed request dict
|
||||||
|
response: ResponseObject for current response
|
||||||
|
|
||||||
|
hook_type: setup/teardown
|
||||||
|
|
||||||
|
"""
|
||||||
|
logger.debug(f"call {hook_type} hook actions.")
|
||||||
|
|
||||||
|
if isinstance(hooks, Dict):
|
||||||
|
# format 1: {"var": "${func()}"}
|
||||||
|
for var_name, hook_content in hooks.items():
|
||||||
|
hook_content_eval = parse_data(
|
||||||
|
hook_content, step_variables, self.__project_meta.functions
|
||||||
|
)
|
||||||
|
logger.debug(
|
||||||
|
f"call hook function: {hook_content}, got value: {hook_content_eval}"
|
||||||
|
)
|
||||||
|
logger.debug(f"assign variable: {var_name} = {hook_content_eval}")
|
||||||
|
step_variables[var_name] = hook_content_eval
|
||||||
|
|
||||||
|
elif isinstance(hooks, List):
|
||||||
|
# format 2: ["${func()}"]
|
||||||
|
for hook in hooks:
|
||||||
|
logger.debug(f"call hook function: {hook}")
|
||||||
|
parse_data(hook, step_variables, self.__project_meta.functions)
|
||||||
|
|
||||||
|
else:
|
||||||
|
logger.warning(f"Invalid hooks format: {hooks}")
|
||||||
|
|
||||||
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)
|
||||||
@@ -101,6 +146,11 @@ class HttpRunner(object):
|
|||||||
"HRUN-Request-ID",
|
"HRUN-Request-ID",
|
||||||
f"HRUN-{self.__case_id}-{str(int(time.time() * 1000))[-6:]}",
|
f"HRUN-{self.__case_id}-{str(int(time.time() * 1000))[-6:]}",
|
||||||
)
|
)
|
||||||
|
step.variables["request"] = parsed_request_dict
|
||||||
|
|
||||||
|
# setup hooks
|
||||||
|
if step.setup_hooks:
|
||||||
|
self.__call_hooks(step.setup_hooks, step.variables, "setup")
|
||||||
|
|
||||||
# prepare arguments
|
# prepare arguments
|
||||||
method = parsed_request_dict.pop("method")
|
method = parsed_request_dict.pop("method")
|
||||||
@@ -112,6 +162,11 @@ class HttpRunner(object):
|
|||||||
# request
|
# request
|
||||||
resp = self.__session.request(method, url, **parsed_request_dict)
|
resp = self.__session.request(method, url, **parsed_request_dict)
|
||||||
resp_obj = ResponseObject(resp)
|
resp_obj = ResponseObject(resp)
|
||||||
|
step.variables["response"] = resp_obj
|
||||||
|
|
||||||
|
# teardown hooks
|
||||||
|
if step.teardown_hooks:
|
||||||
|
self.__call_hooks(step.teardown_hooks, step.variables, "teardown")
|
||||||
|
|
||||||
def log_req_resp_details():
|
def log_req_resp_details():
|
||||||
err_msg = "\n{} DETAILED REQUEST & RESPONSE {}\n".format("*" * 32, "*" * 32)
|
err_msg = "\n{} DETAILED REQUEST & RESPONSE {}\n".format("*" * 32, "*" * 32)
|
||||||
|
|||||||
Reference in New Issue
Block a user