mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-09 06:23:52 +08:00
feat: dump log for each testcase
This commit is contained in:
@@ -1,12 +1,13 @@
|
|||||||
# Release History
|
# Release History
|
||||||
|
|
||||||
## 3.0.5 (2020-05-21)
|
## 3.0.5 (2020-05-22)
|
||||||
|
|
||||||
**Added**
|
**Added**
|
||||||
|
|
||||||
- feat: each testcase has an unique id in uuid4 format
|
- feat: each testcase has an unique id in uuid4 format
|
||||||
- feat: add default header `HRUN-Request-ID` for each testcase #721
|
- feat: add default header `HRUN-Request-ID` for each testcase #721
|
||||||
- feat: builtin allure report
|
- feat: builtin allure report
|
||||||
|
- feat: dump log for each testcase
|
||||||
|
|
||||||
**Fixed**
|
**Fixed**
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ class HttpSession(requests.Session):
|
|||||||
logger.info(
|
logger.info(
|
||||||
f"status_code: {response.status_code}, "
|
f"status_code: {response.status_code}, "
|
||||||
f"response_time(ms): {response_time_ms} ms, "
|
f"response_time(ms): {response_time_ms} ms, "
|
||||||
f"response_length: {content_size} bytes\n"
|
f"response_length: {content_size} bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|||||||
@@ -33,12 +33,15 @@ class HttpRunner(object):
|
|||||||
|
|
||||||
success: bool = True # indicate testcase execution result
|
success: bool = True # indicate testcase execution result
|
||||||
__project_meta: ProjectMeta = None
|
__project_meta: ProjectMeta = None
|
||||||
__case_id: Text = None
|
__case_id: Text = ""
|
||||||
__step_datas: List[StepData] = None
|
__step_datas: List[StepData] = None
|
||||||
__session: HttpSession = None
|
__session: HttpSession = None
|
||||||
__session_variables: VariablesMapping = {}
|
__session_variables: VariablesMapping = {}
|
||||||
__start_at = 0
|
# time
|
||||||
__duration = 0
|
__start_at: float = 0
|
||||||
|
__duration: float = 0
|
||||||
|
# log
|
||||||
|
__log_path: Text = ""
|
||||||
|
|
||||||
def with_project_meta(self, project_meta: ProjectMeta) -> "HttpRunner":
|
def with_project_meta(self, project_meta: ProjectMeta) -> "HttpRunner":
|
||||||
self.__project_meta = project_meta
|
self.__project_meta = project_meta
|
||||||
@@ -170,41 +173,36 @@ class HttpRunner(object):
|
|||||||
logger.info(f"run step end: {step.name} <<<<<<\n")
|
logger.info(f"run step end: {step.name} <<<<<<\n")
|
||||||
return step_data.export
|
return step_data.export
|
||||||
|
|
||||||
def run(self, testcase: TestCase):
|
def __parse_config(self, config: TConfig):
|
||||||
"""main entrance"""
|
if config.path:
|
||||||
self.config = testcase.config
|
self.__project_meta = load_project_meta(config.path)
|
||||||
self.teststeps = testcase.teststeps
|
|
||||||
|
|
||||||
self.__case_id = self.__case_id or str(uuid.uuid4())
|
|
||||||
logger.info(f"Start to run testcase: {self.config.name}, TestCase ID: {self.__case_id}")
|
|
||||||
|
|
||||||
if self.config.path:
|
|
||||||
self.__project_meta = load_project_meta(self.config.path)
|
|
||||||
elif not self.__project_meta:
|
elif not self.__project_meta:
|
||||||
self.__project_meta = ProjectMeta()
|
self.__project_meta = ProjectMeta()
|
||||||
|
|
||||||
def parse_config(config: TConfig):
|
config.variables.update(self.__session_variables)
|
||||||
config.variables = parse_variables_mapping(
|
config.variables = parse_variables_mapping(
|
||||||
config.variables, self.__project_meta.functions
|
config.variables, self.__project_meta.functions
|
||||||
)
|
)
|
||||||
config.name = parse_data(
|
config.name = parse_data(
|
||||||
config.name, config.variables, self.__project_meta.functions
|
config.name, config.variables, self.__project_meta.functions
|
||||||
)
|
)
|
||||||
config.base_url = parse_data(
|
config.base_url = parse_data(
|
||||||
config.base_url, config.variables, self.__project_meta.functions
|
config.base_url, config.variables, self.__project_meta.functions
|
||||||
)
|
)
|
||||||
|
|
||||||
self.config.variables.update(self.__session_variables)
|
def run(self, testcase: TestCase):
|
||||||
parse_config(self.config)
|
"""run testcase"""
|
||||||
|
self.config = testcase.config
|
||||||
|
self.teststeps = testcase.teststeps
|
||||||
|
|
||||||
|
# prepare
|
||||||
|
self.__parse_config(self.config)
|
||||||
self.__start_at = time.time()
|
self.__start_at = time.time()
|
||||||
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 = {}
|
||||||
|
|
||||||
# update allure report meta
|
# run teststeps
|
||||||
allure.dynamic.title(self.config.name)
|
|
||||||
allure.dynamic.description(f"TestCase ID: {self.__case_id}")
|
|
||||||
|
|
||||||
for step in self.teststeps:
|
for step in self.teststeps:
|
||||||
# update with config variables
|
# update with config variables
|
||||||
step.variables.update(self.config.variables)
|
step.variables.update(self.config.variables)
|
||||||
@@ -252,6 +250,7 @@ class HttpRunner(object):
|
|||||||
return TestCaseSummary(
|
return TestCaseSummary(
|
||||||
name=self.config.name,
|
name=self.config.name,
|
||||||
success=self.success,
|
success=self.success,
|
||||||
|
case_id=self.__case_id,
|
||||||
time=TestCaseTime(
|
time=TestCaseTime(
|
||||||
start_at=self.__start_at,
|
start_at=self.__start_at,
|
||||||
start_at_iso_format=start_at_iso_format,
|
start_at_iso_format=start_at_iso_format,
|
||||||
@@ -260,9 +259,29 @@ class HttpRunner(object):
|
|||||||
in_out=TestCaseInOut(
|
in_out=TestCaseInOut(
|
||||||
vars=self.config.variables, export=self.get_export_variables()
|
vars=self.config.variables, export=self.get_export_variables()
|
||||||
),
|
),
|
||||||
|
log=self.__log_path,
|
||||||
step_datas=self.__step_datas,
|
step_datas=self.__step_datas,
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_start(self):
|
def test_start(self):
|
||||||
"""discovered by pytest"""
|
"""main entrance, discovered by pytest"""
|
||||||
return self.run(TestCase(config=self.config, teststeps=self.teststeps))
|
self.__case_id = self.__case_id or str(uuid.uuid4())
|
||||||
|
self.__log_path = self.__log_path or os.path.join(
|
||||||
|
"logs", f"{self.__case_id}.run.log"
|
||||||
|
)
|
||||||
|
log_handler = logger.add(self.__log_path, level="DEBUG")
|
||||||
|
|
||||||
|
# update allure report meta
|
||||||
|
# TODO: parse config name
|
||||||
|
allure.dynamic.title(self.config.name)
|
||||||
|
allure.dynamic.description(f"TestCase ID: {self.__case_id}")
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"Start to run testcase: {self.config.name}, TestCase ID: {self.__case_id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return self.run(TestCase(config=self.config, teststeps=self.teststeps))
|
||||||
|
finally:
|
||||||
|
logger.remove(log_handler)
|
||||||
|
logger.info(f"generate testcase log: {self.__log_path}")
|
||||||
|
|||||||
@@ -147,8 +147,9 @@ class StepData(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class TestCaseSummary(BaseModel):
|
class TestCaseSummary(BaseModel):
|
||||||
name: Text = ""
|
name: Text
|
||||||
success: bool = False
|
success: bool
|
||||||
|
case_id: Text
|
||||||
time: TestCaseTime
|
time: TestCaseTime
|
||||||
in_out: TestCaseInOut = {}
|
in_out: TestCaseInOut = {}
|
||||||
log: Text = ""
|
log: Text = ""
|
||||||
|
|||||||
Reference in New Issue
Block a user