向 TestReport 对象添加新字段并在 pytest_html_results_table_html 挂钩中使用它
Adding new field to TestReport object and using it in pytest_html_results_table_html hook
我想获取有关在测试 call
阶段引发的异常的信息,并将它们添加到使用 pytest-html
插件创建的报告中。所以我为 pytest_runtest_makereport
创建了 hookwrapper
:
@hookimpl(hookwrapper=True)
def pytest_runtest_makereport(call):
outcome = yield
result = outcome.get_result()
errors = getattr(result, "errors", [])
if result.when == "call":
if result.failed:
if error := call.excinfo:
errors.append(error.typename)
result.errors = errors
else:
logger.info("PASSED")
要将此信息添加到测试报告中,我正在使用:
def pytest_html_results_table_html(report, data):
del data[:]
if errors := getattr(report, "errors", []):
data.append(html.div(", ".join(errors), class_="failed log"))
不幸的是,在 pytest_html_results_table_html
中,报表实例中没有错误字段。如果我将 result.errors = errors
添加到拆卸阶段,字段会出现在报告对象中,但它有空列表。
我知道有一个 extra
字段,但 pytest-html
将其直接添加到报告中。我想在添加这些值之前对其进行一些处理。
那么我在这里缺少什么?如何将此值从 pytest_runtest_makereport
传递到 pytest_html_results_table_html
?
我正在使用的示例测试 class:
from logging import getLogger
from pytest import fixture
logger = getLogger()
class TestVariousOutputs:
@fixture()
def setup(self):
logger.info("Run setup")
raise RuntimeError("Error raised during setup")
@fixture()
def teardown(self):
logger.info("Run setup")
yield
logger.info("Run teardown")
raise RuntimeError("Error raised during teardown")
def test_pass(self):
logger.info("Run test")
assert True
def test_fail(self):
logger.info("Run test")
assert False, "Assert False"
def test_raise_error(self):
logger.info("Run test")
raise RuntimeError("Error raised during test run")
def test_setup_raise_error(self, setup):
logger.info("Run test")
assert True
def test_teardown_raise_error(self, teardown):
logger.info("Run test")
assert True
def test_teardown_raise_error_and_test_fails(self, teardown):
logger.info("Run test")
assert False, "Assert False but teardown should also fail"
因为 pytest-html
目前是这样实现的:对于每个测试用例,它将获取 teardown
报告并从 call
和 setup
中复制选定的字段报道。当然,自定义字段会被忽略(呃!)。因此,您必须拦截此 post-对 pytest
报告的处理,并确保您的自定义字段出现在 teardown
报告中。放入 conftest.py
的示例:
@pytest.hookimpl(tryfirst=True) # run our hookimpl before pytest-html does its own postprocessing
def pytest_sessionfinish(session):
html_report = getattr(session.config, "_html", None)
for rep_setup, rep_call, rep_teardown in html_report.reports.values():
# copy errors field from call report to teardown report
rep_teardown.errors = getattr(rep_call, "errors", [])
我想获取有关在测试 call
阶段引发的异常的信息,并将它们添加到使用 pytest-html
插件创建的报告中。所以我为 pytest_runtest_makereport
创建了 hookwrapper
:
@hookimpl(hookwrapper=True)
def pytest_runtest_makereport(call):
outcome = yield
result = outcome.get_result()
errors = getattr(result, "errors", [])
if result.when == "call":
if result.failed:
if error := call.excinfo:
errors.append(error.typename)
result.errors = errors
else:
logger.info("PASSED")
要将此信息添加到测试报告中,我正在使用:
def pytest_html_results_table_html(report, data):
del data[:]
if errors := getattr(report, "errors", []):
data.append(html.div(", ".join(errors), class_="failed log"))
不幸的是,在 pytest_html_results_table_html
中,报表实例中没有错误字段。如果我将 result.errors = errors
添加到拆卸阶段,字段会出现在报告对象中,但它有空列表。
我知道有一个 extra
字段,但 pytest-html
将其直接添加到报告中。我想在添加这些值之前对其进行一些处理。
那么我在这里缺少什么?如何将此值从 pytest_runtest_makereport
传递到 pytest_html_results_table_html
?
我正在使用的示例测试 class:
from logging import getLogger
from pytest import fixture
logger = getLogger()
class TestVariousOutputs:
@fixture()
def setup(self):
logger.info("Run setup")
raise RuntimeError("Error raised during setup")
@fixture()
def teardown(self):
logger.info("Run setup")
yield
logger.info("Run teardown")
raise RuntimeError("Error raised during teardown")
def test_pass(self):
logger.info("Run test")
assert True
def test_fail(self):
logger.info("Run test")
assert False, "Assert False"
def test_raise_error(self):
logger.info("Run test")
raise RuntimeError("Error raised during test run")
def test_setup_raise_error(self, setup):
logger.info("Run test")
assert True
def test_teardown_raise_error(self, teardown):
logger.info("Run test")
assert True
def test_teardown_raise_error_and_test_fails(self, teardown):
logger.info("Run test")
assert False, "Assert False but teardown should also fail"
因为 pytest-html
目前是这样实现的:对于每个测试用例,它将获取 teardown
报告并从 call
和 setup
中复制选定的字段报道。当然,自定义字段会被忽略(呃!)。因此,您必须拦截此 post-对 pytest
报告的处理,并确保您的自定义字段出现在 teardown
报告中。放入 conftest.py
的示例:
@pytest.hookimpl(tryfirst=True) # run our hookimpl before pytest-html does its own postprocessing
def pytest_sessionfinish(session):
html_report = getattr(session.config, "_html", None)
for rep_setup, rep_call, rep_teardown in html_report.reports.values():
# copy errors field from call report to teardown report
rep_teardown.errors = getattr(rep_call, "errors", [])