自定义 pytest junitxml 失败报告
Customizing pytest junitxml failure reports
我正在尝试反省测试失败并将其他数据包含到 junit xml 测试报告中。具体来说,这是一套针对外部产品的功能测试,我想将产品的日志包含在故障报告中。
使用找到的方法 here,我能够在执行 multicall 之前将日志打印到 stdout,最终显示在 jenkin 的失败报告中。但我确信有更好的方法来实现这一目标。
我尝试使用 pytest_runtest_logreport 挂钩将日志附加到 'sections' 属性中,该属性已经包含 'captured stdout' 和 'captured stderr' 流。但是新添加的部分不会进入 xml 文件。我也在 pytest_runtest_makereport 挂钩中直接尝试了上述技术,结果相似。
pytest 2.7 的发行说明指出 2.8 不再使用多调用支持,@pytest.mark.hookwrapper 是新的方法,但我似乎根本无法做到这一点 - "yield" returns None 而不是 CallOutcome 对象(在 makereport 挂钩中尝试过)。即使它返回了一些东西,我也不确定我是否可以向它添加会显示在 xml 报告中的东西。
是否有任何我缺少的功能可以让我以灵活的方式执行此操作? (灵活的意思是:不被绑定到标准输出或像捕获日志插件那样记录调用)
要向测试报告(XML、控制台或其他)添加信息,请查看 reporting hooks, more specifically at pytest_runtest_logreport。
编辑:由于我需要访问测试项目的 funcargs(和测试结果)以进行报告,因此我能够将逻辑移至 pytest_runtest_makereport(item, __multicall__)
挂钩。诀窍是执行多重调用,returns 报告 object:
@pytest.mark.tryfirst
def pytest_runtest_makereport(item, call, __multicall__):
report = __multicall__.execute()
# then I was able to manipulate report and get the same results as below
Bruno 的回答给了我更彻底分析此功能所需的动力:)
它是这样工作的:
def pytest_runtest_logreport(report):
if report.failed:
report.longrepr.sections.append(("Header", "Message", "-"))
report.sections.append(("Captured stdout", "This is added to stdout"))
report.sections.append(("Captured stderr", "This is added to stderr"))
report.sections.append(("Custom Section", "This can only be seen in the console - the xml won't have it."))
longrepr
属性仅在失败时可用。它需要一个 3 元组,最后一个值是用来修饰 decorate/surround 和 header 的字符。它将出现在报告的 "failure" 部分:
----------------------------------- Header ------------------------------------
Message
自定义部分将创建额外的结果部分以打印到控制台。但他们不会进入 junitxml:
------------------------------- Custom Section --------------------------------
This can only be seen in the console - the xml won't have it.
junitxml 报告只有 2 个部分:out 和 err。要向其中添加自定义文本,您必须创建名为 "Captured std" 的部分,并且只有这些部分才能进入 xml 文件。任何其他名称将生成一个只能在控制台中看到的自定义部分。
这是使用上面的代码生成的 junitxml,为此需要重新格式化 post:
<?xml version="1.0" encoding="utf-8" ?>
<testsuite errors="0" failures="1" name="pytest" skips="0" tests="1" time="0.646">
<testcase classname="test_reporting" name="test_fail" time="0.000999927520752">
<failure message="test failure">
@ut def test_fail(): > assert 0, "It failed"
E AssertionError: It failed
E assert 0 test_reporting.py:346: AssertionError
----------------------------------- Header ------------------------------------
Message
</failure>
<system-out>This is added to stdout</system-out>
<system-err>This is added to stderr</system-err>
</testcase>
</testsuite>
将 pytest_runtest_makereport(item, call)
与 @pytest.hookimpl(hookwrapper=True)
结合使用允许在使用报告创建 xml 之前访问报告,例如
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
result = yield
if result.get_result().failed:
report.longrepr.addsection("Header","message")
使用 pytest-3.9.3
虽然 the documentation 对于 hookwrapper 确实建议谨慎
If the result of the underlying hook is a mutable object, they may modify that result but it’s probably better to avoid it.
我正在尝试反省测试失败并将其他数据包含到 junit xml 测试报告中。具体来说,这是一套针对外部产品的功能测试,我想将产品的日志包含在故障报告中。
使用找到的方法 here,我能够在执行 multicall 之前将日志打印到 stdout,最终显示在 jenkin 的失败报告中。但我确信有更好的方法来实现这一目标。
我尝试使用 pytest_runtest_logreport 挂钩将日志附加到 'sections' 属性中,该属性已经包含 'captured stdout' 和 'captured stderr' 流。但是新添加的部分不会进入 xml 文件。我也在 pytest_runtest_makereport 挂钩中直接尝试了上述技术,结果相似。
pytest 2.7 的发行说明指出 2.8 不再使用多调用支持,@pytest.mark.hookwrapper 是新的方法,但我似乎根本无法做到这一点 - "yield" returns None 而不是 CallOutcome 对象(在 makereport 挂钩中尝试过)。即使它返回了一些东西,我也不确定我是否可以向它添加会显示在 xml 报告中的东西。
是否有任何我缺少的功能可以让我以灵活的方式执行此操作? (灵活的意思是:不被绑定到标准输出或像捕获日志插件那样记录调用)
要向测试报告(XML、控制台或其他)添加信息,请查看 reporting hooks, more specifically at pytest_runtest_logreport。
编辑:由于我需要访问测试项目的 funcargs(和测试结果)以进行报告,因此我能够将逻辑移至 pytest_runtest_makereport(item, __multicall__)
挂钩。诀窍是执行多重调用,returns 报告 object:
@pytest.mark.tryfirst
def pytest_runtest_makereport(item, call, __multicall__):
report = __multicall__.execute()
# then I was able to manipulate report and get the same results as below
Bruno 的回答给了我更彻底分析此功能所需的动力:)
它是这样工作的:
def pytest_runtest_logreport(report):
if report.failed:
report.longrepr.sections.append(("Header", "Message", "-"))
report.sections.append(("Captured stdout", "This is added to stdout"))
report.sections.append(("Captured stderr", "This is added to stderr"))
report.sections.append(("Custom Section", "This can only be seen in the console - the xml won't have it."))
longrepr
属性仅在失败时可用。它需要一个 3 元组,最后一个值是用来修饰 decorate/surround 和 header 的字符。它将出现在报告的 "failure" 部分:
----------------------------------- Header ------------------------------------
Message
自定义部分将创建额外的结果部分以打印到控制台。但他们不会进入 junitxml:
------------------------------- Custom Section --------------------------------
This can only be seen in the console - the xml won't have it.
junitxml 报告只有 2 个部分:out 和 err。要向其中添加自定义文本,您必须创建名为 "Captured std" 的部分,并且只有这些部分才能进入 xml 文件。任何其他名称将生成一个只能在控制台中看到的自定义部分。
这是使用上面的代码生成的 junitxml,为此需要重新格式化 post:
<?xml version="1.0" encoding="utf-8" ?>
<testsuite errors="0" failures="1" name="pytest" skips="0" tests="1" time="0.646">
<testcase classname="test_reporting" name="test_fail" time="0.000999927520752">
<failure message="test failure">
@ut def test_fail(): > assert 0, "It failed"
E AssertionError: It failed
E assert 0 test_reporting.py:346: AssertionError
----------------------------------- Header ------------------------------------
Message
</failure>
<system-out>This is added to stdout</system-out>
<system-err>This is added to stderr</system-err>
</testcase>
</testsuite>
将 pytest_runtest_makereport(item, call)
与 @pytest.hookimpl(hookwrapper=True)
结合使用允许在使用报告创建 xml 之前访问报告,例如
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
result = yield
if result.get_result().failed:
report.longrepr.addsection("Header","message")
使用 pytest-3.9.3
虽然 the documentation 对于 hookwrapper 确实建议谨慎
If the result of the underlying hook is a mutable object, they may modify that result but it’s probably better to avoid it.