mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-08 09:19:41 +08:00
refactor: adjust summary data structure
This commit is contained in:
@@ -3,8 +3,6 @@ import unittest
|
|||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from httprunner.v3.schema import Record
|
|
||||||
|
|
||||||
|
|
||||||
class HtmlTestResult(unittest.TextTestResult):
|
class HtmlTestResult(unittest.TextTestResult):
|
||||||
""" A html result class that can generate formatted html results, used by TextTestRunner.
|
""" A html result class that can generate formatted html results, used by TextTestRunner.
|
||||||
@@ -12,13 +10,16 @@ class HtmlTestResult(unittest.TextTestResult):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, stream, descriptions, verbosity):
|
def __init__(self, stream, descriptions, verbosity):
|
||||||
super(HtmlTestResult, self).__init__(stream, descriptions, verbosity)
|
super(HtmlTestResult, self).__init__(stream, descriptions, verbosity)
|
||||||
self.record = Record()
|
self.name = ""
|
||||||
|
self.status = ""
|
||||||
|
self.attachment = ""
|
||||||
|
self.meta_datas = None
|
||||||
|
|
||||||
def _record_test(self, test, status, attachment=''):
|
def _record_test(self, test, status, attachment=''):
|
||||||
self.record.name = test.shortDescription()
|
self.name = test.shortDescription()
|
||||||
self.record.status = status
|
self.status = status
|
||||||
self.record.attachment = attachment
|
self.attachment = attachment
|
||||||
self.record.meta_datas = test.meta_datas
|
self.meta_datas = test.meta_datas
|
||||||
|
|
||||||
def startTestRun(self):
|
def startTestRun(self):
|
||||||
self.start_at = time.time()
|
self.start_at = time.time()
|
||||||
|
|||||||
@@ -206,7 +206,6 @@ def stringify_summary(testsuite_summary: TestSuiteSummary):
|
|||||||
if not testcase_summary.name:
|
if not testcase_summary.name:
|
||||||
testcase_summary.name = f"testcase {index}"
|
testcase_summary.name = f"testcase {index}"
|
||||||
|
|
||||||
record = testcase_summary.record
|
meta_datas = testcase_summary.meta_datas
|
||||||
meta_datas = record.meta_datas
|
|
||||||
__stringify_meta_datas(meta_datas)
|
__stringify_meta_datas(meta_datas)
|
||||||
record.response_time = __get_total_response_time(meta_datas)
|
testcase_summary.total_response_time = __get_total_response_time(meta_datas)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import platform
|
|||||||
|
|
||||||
from httprunner import __version__
|
from httprunner import __version__
|
||||||
from httprunner.report.html.result import HtmlTestResult
|
from httprunner.report.html.result import HtmlTestResult
|
||||||
from httprunner.v3.schema import TestCaseSummary, TestCaseStat, TestCaseTime, TestCaseInOut
|
from httprunner.v3.schema import TestCaseSummary, TestCaseTime, TestCaseInOut
|
||||||
|
|
||||||
|
|
||||||
def get_platform():
|
def get_platform():
|
||||||
@@ -59,18 +59,13 @@ def get_summary(result: HtmlTestResult) -> TestCaseSummary:
|
|||||||
"""
|
"""
|
||||||
return TestCaseSummary(
|
return TestCaseSummary(
|
||||||
success=result.wasSuccessful(),
|
success=result.wasSuccessful(),
|
||||||
stat=TestCaseStat(
|
|
||||||
total=result.testsRun,
|
|
||||||
failures=len(result.failures),
|
|
||||||
errors=len(result.errors),
|
|
||||||
skipped=len(result.skipped),
|
|
||||||
expectedFailures=len(result.expectedFailures),
|
|
||||||
unexpectedSuccesses=len(result.unexpectedSuccesses)
|
|
||||||
),
|
|
||||||
time=TestCaseTime(
|
time=TestCaseTime(
|
||||||
start_at=result.start_at,
|
start_at=result.start_at,
|
||||||
duration=result.duration
|
duration=result.duration
|
||||||
),
|
),
|
||||||
record=result.record,
|
name=result.name,
|
||||||
in_out=TestCaseInOut()
|
status=result.status,
|
||||||
|
attachment=result.attachment,
|
||||||
|
in_out=TestCaseInOut(),
|
||||||
|
meta_datas=result.meta_datas
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ class HttpRunner(object):
|
|||||||
|
|
||||||
result = self.unittest_runner.run(testcase)
|
result = self.unittest_runner.run(testcase)
|
||||||
testcase_summary = report.get_summary(result)
|
testcase_summary = report.get_summary(result)
|
||||||
testcase_summary.name = testcase.config.name
|
|
||||||
testcase_summary.in_out.vars = testcase.config.variables
|
testcase_summary.in_out.vars = testcase.config.variables
|
||||||
testcase_summary.in_out.out = testcase.config.export
|
testcase_summary.in_out.out = testcase.config.export
|
||||||
|
|
||||||
@@ -136,12 +135,9 @@ class HttpRunner(object):
|
|||||||
testsuite_summary = {
|
testsuite_summary = {
|
||||||
"success": True,
|
"success": True,
|
||||||
"stat": {
|
"stat": {
|
||||||
"testcases": {
|
"total": len(tests_results),
|
||||||
"total": len(tests_results),
|
"success": 0,
|
||||||
"success": 0,
|
"fail": 0
|
||||||
"fail": 0
|
|
||||||
},
|
|
||||||
"teststeps": {}
|
|
||||||
},
|
},
|
||||||
"time": {},
|
"time": {},
|
||||||
"platform": report.get_platform(),
|
"platform": report.get_platform(),
|
||||||
@@ -150,13 +146,11 @@ class HttpRunner(object):
|
|||||||
|
|
||||||
for testcase_summary in tests_results:
|
for testcase_summary in tests_results:
|
||||||
if testcase_summary.success:
|
if testcase_summary.success:
|
||||||
testsuite_summary["stat"]["testcases"]["success"] += 1
|
testsuite_summary["stat"]["success"] += 1
|
||||||
else:
|
else:
|
||||||
testsuite_summary["stat"]["testcases"]["fail"] += 1
|
testsuite_summary["stat"]["fail"] += 1
|
||||||
|
|
||||||
testsuite_summary["success"] &= testcase_summary.success
|
testsuite_summary["success"] &= testcase_summary.success
|
||||||
|
|
||||||
report.aggregate_stat(testsuite_summary["stat"]["teststeps"], testcase_summary.stat.dict())
|
|
||||||
report.aggregate_stat(testsuite_summary["time"], testcase_summary.time.dict())
|
report.aggregate_stat(testsuite_summary["time"], testcase_summary.time.dict())
|
||||||
|
|
||||||
testsuite_summary["details"].append(testcase_summary)
|
testsuite_summary["details"].append(testcase_summary)
|
||||||
@@ -197,7 +191,7 @@ class HttpRunner(object):
|
|||||||
utils.prepare_log_file_abs_path(self.test_path, "summary.json")
|
utils.prepare_log_file_abs_path(self.test_path, "summary.json")
|
||||||
)
|
)
|
||||||
# save variables and export data
|
# save variables and export data
|
||||||
vars_out = self.get_vars_out() # TODO
|
vars_out = self.get_vars_out()
|
||||||
utils.dump_json_file(
|
utils.dump_json_file(
|
||||||
vars_out,
|
vars_out,
|
||||||
utils.prepare_log_file_abs_path(self.test_path, "io.json")
|
utils.prepare_log_file_abs_path(self.test_path, "io.json")
|
||||||
@@ -205,6 +199,35 @@ class HttpRunner(object):
|
|||||||
|
|
||||||
return self._summary
|
return self._summary
|
||||||
|
|
||||||
|
def get_vars_out(self):
|
||||||
|
""" get variables and output
|
||||||
|
Returns:
|
||||||
|
list: list of variables and output.
|
||||||
|
if tests are parameterized, list items are corresponded to parameters.
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"in": {
|
||||||
|
"user1": "leo"
|
||||||
|
},
|
||||||
|
"out": {
|
||||||
|
"out1": "out_value_1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{...}
|
||||||
|
]
|
||||||
|
|
||||||
|
None: returns None if tests not started or finished or corrupted.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not self._summary:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return [
|
||||||
|
testcase_summary.in_out.dict()
|
||||||
|
for testcase_summary in self._summary.details
|
||||||
|
]
|
||||||
|
|
||||||
def run_path(self, path, dot_env_path=None, mapping=None) -> TestSuiteSummary:
|
def run_path(self, path, dot_env_path=None, mapping=None) -> TestSuiteSummary:
|
||||||
""" run testcase/testsuite file or folder.
|
""" run testcase/testsuite file or folder.
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,5 @@ class TestHttpRunner(unittest.TestCase):
|
|||||||
summary = self.runner.run_path("examples/postman_echo/request_methods/")
|
summary = self.runner.run_path("examples/postman_echo/request_methods/")
|
||||||
self.assertTrue(summary.success)
|
self.assertTrue(summary.success)
|
||||||
self.assertEqual(summary.details[0].name, "request methods testcase with variables")
|
self.assertEqual(summary.details[0].name, "request methods testcase with variables")
|
||||||
self.assertEqual(summary.details[0].record.name, "request methods testcase with variables")
|
self.assertGreater(summary.stat.total, 1)
|
||||||
self.assertEqual(summary.stat.testcases["total"], 1)
|
|
||||||
# self.assertEqual(summary.stat.teststeps["total"], 2)
|
# self.assertEqual(summary.stat.teststeps["total"], 2)
|
||||||
|
|||||||
@@ -82,27 +82,12 @@ class TestsMapping(BaseModel):
|
|||||||
testcases: List[TestCase]
|
testcases: List[TestCase]
|
||||||
|
|
||||||
|
|
||||||
class Stat(BaseModel):
|
|
||||||
testcases: Dict
|
|
||||||
teststeps: Dict
|
|
||||||
|
|
||||||
|
|
||||||
class TestCaseTime(BaseModel):
|
class TestCaseTime(BaseModel):
|
||||||
start_at: float
|
start_at: float
|
||||||
duration: float
|
duration: float
|
||||||
start_datetime: Text = ""
|
start_datetime: Text = ""
|
||||||
|
|
||||||
|
|
||||||
class TestCaseStat(BaseModel):
|
|
||||||
total: int = 0
|
|
||||||
successes: int = 0
|
|
||||||
failures: int = 0
|
|
||||||
errors: int = 0
|
|
||||||
skipped: int = 0
|
|
||||||
expectedFailures: int = 0
|
|
||||||
unexpectedSuccesses: int = 0
|
|
||||||
|
|
||||||
|
|
||||||
class TestCaseInOut(BaseModel):
|
class TestCaseInOut(BaseModel):
|
||||||
vars: VariablesMapping = {}
|
vars: VariablesMapping = {}
|
||||||
out: Export = []
|
out: Export = []
|
||||||
@@ -121,22 +106,16 @@ class MetaData(BaseModel):
|
|||||||
validators: Dict = {}
|
validators: Dict = {}
|
||||||
|
|
||||||
|
|
||||||
class Record(BaseModel):
|
|
||||||
name: Text = ""
|
|
||||||
status: Text = ""
|
|
||||||
attachment: Text = ""
|
|
||||||
meta_datas: List[MetaData] = []
|
|
||||||
response_time: Text = "N/A"
|
|
||||||
|
|
||||||
|
|
||||||
class TestCaseSummary(BaseModel):
|
class TestCaseSummary(BaseModel):
|
||||||
name: Text = ""
|
name: Text = ""
|
||||||
success: bool
|
success: bool
|
||||||
stat: TestCaseStat
|
status: Text = ""
|
||||||
|
attachment: Text = ""
|
||||||
time: TestCaseTime
|
time: TestCaseTime
|
||||||
record: Record = {}
|
|
||||||
in_out: TestCaseInOut = {}
|
in_out: TestCaseInOut = {}
|
||||||
log: Text = ""
|
log: Text = ""
|
||||||
|
meta_datas: List[MetaData] = []
|
||||||
|
total_response_time: Text = "N/A"
|
||||||
|
|
||||||
|
|
||||||
class PlatformInfo(BaseModel):
|
class PlatformInfo(BaseModel):
|
||||||
@@ -145,6 +124,12 @@ class PlatformInfo(BaseModel):
|
|||||||
platform: Text
|
platform: Text
|
||||||
|
|
||||||
|
|
||||||
|
class Stat(BaseModel):
|
||||||
|
total: int = 0
|
||||||
|
success: int = 0
|
||||||
|
fail: int = 0
|
||||||
|
|
||||||
|
|
||||||
class TestSuiteSummary(BaseModel):
|
class TestSuiteSummary(BaseModel):
|
||||||
success: bool
|
success: bool
|
||||||
stat: Stat
|
stat: Stat
|
||||||
|
|||||||
Reference in New Issue
Block a user