自定义pytest junitxml失败报告

Joe*_*Joe 6 python logging pytest

我试图反省测试失败并将其他数据包含在junit xml测试报告中.具体来说,这是一套外部产品的功能测试,我想将产品的日志包含在故障报告中.

使用这里找到的方法,我能够在执行multicall之前将日志打印到stdout,最终显示在jenkin的失败报告中.但我确信有更好的方法来实现这一目标.

我尝试使用pytest_runtest_logreport钩子将日志附加到'sections'属性中,该属性已经包含'capture stdout'和'capture stderr'流.但是新添加的部分没有进入xml文件.我也尝试将上述技术直接导入到pytest_runtest_makereport钩子中,结果相似.

pytest 2.7的发行说明指出,使用多路支持将被删除2.8并且@ pytest.mark.hookwrapper是新的方法,但是我似乎无法完成这项工作 - "收益"返回没有而不是CallOutcome对象(在makereport钩子中尝试过).即使它返回了某些内容,我也不确定是否可以在xml报告中添加内容.

是否有任何我缺少的功能可以让我以灵活的方式做到这一点?(灵活的我的意思是:不被绑定到stdout或记录像capture-logs插件这样的调用)

Joe*_*Joe 6

编辑:因为我需要访问测试项目的funcargs(和测试结果)来进行报告,所以我能够将逻辑移到pytest_runtest_makereport(item, __multicall__)钩子上.诀窍是执行multiicall,它返回报表对象:

@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
Run Code Online (Sandbox Code Playgroud)

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."))
Run Code Online (Sandbox Code Playgroud)

longrepr属性仅在出现故障时可用.它需要一个3元组,最后一个值是用于装饰装饰/环绕标题的字符.它将出现在报告的"失败"部分:

----------------------------------- Header ------------------------------------
Message
Run Code Online (Sandbox Code Playgroud)

自定义部分将创建要打印到控制台的其他结果部分.但他们不会成功到junitxml:

------------------------------- Custom Section --------------------------------
This can only be seen in the console - the xml won't have it.
Run Code Online (Sandbox Code Playgroud)

junitxml报告只有2个部分:out和err.要向其添加自定义文本,您必须创建名为"Captured std"的部分,并且只有那些将使其成为xml文件.任何其他名称将导致只在控制台中看到的自定义部分.

这是使用上面代码生成的junitxml,为了这篇文章的一些重新格式化:

<?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>
Run Code Online (Sandbox Code Playgroud)