pytest capsys:检查输出并报告?

Lut*_*elt 12 python pytest

Python 3.4.1,pytest 2.6.2.

当测试失败时,pytest将定期报告测试中打印到stdout的内容.例如这段代码:

def method_under_test():
    print("Hallo, Welt!")
    return 41

def test_result_only():
    result = method_under_test()
    assert result == 42
Run Code Online (Sandbox Code Playgroud)

执行时python -m pytest myfile.py,将报告此:

================================== FAILURES ===================================
______________________________ test_result_only _______________________________

    def test_result_only():
        result = method_under_test()
>       assert result == 42
E       assert 41 == 42

pytestest.py:9: AssertionError
---------------------------- Captured stdout call -----------------------------
Hallo, Welt!
========================== 1 failed in 0.03 seconds ===========================
Run Code Online (Sandbox Code Playgroud)

这是一个非常好的功能.但是当我使用pytest的内置capsys夹具时,如下所示:

def test_result_and_stdout(capsys):
    result = method_under_test()
    out, err = capsys.readouterr()
    assert out.startswith("Hello")
    assert result == 42
Run Code Online (Sandbox Code Playgroud)

报告不再包含实际输出:

================================== FAILURES ===================================
___________________________ test_result_and_stdout ____________________________

capsys = <_pytest.capture.CaptureFixture object at 0x000000000331FB70>

    def test_result_and_stdout(capsys):
        result = method_under_test()
        out, err = capsys.readouterr()
>       assert out.startswith("Hello")
E       assert <built-in method startswith of str object at 0x000000000330C3B0>('Hello')
E        +  where <built-in method startswith of str object at 0x000000000330C3B0> = 'Hallo, Welt!\n'.startswith

pytestest.py:14: AssertionError
========================== 1 failed in 0.03 seconds ===========================
Run Code Online (Sandbox Code Playgroud)

我不确定这种行为是否符合规范; 在pytest文件说,有关readouterr"测试功能完成对原始流将被恢复后."

我试过假设capsys是一个上下文管理器,并capsys.__exit__()在断言之前调用.这将是一个丑陋的解决方案,但至少是一个解决方案,如果它在我的断言之前恢复输出.但是,这只会产生

AttributeError: 'CaptureFixture' object has no attribute '__exit__'
Run Code Online (Sandbox Code Playgroud)

接下来,我查看了CaptureFixture类源代码,发现了一个很有前途的方法close(调用了一些pop_outerr_to_orig()方法),但是capsys.close()在我的测试中调用也没有帮助,它根本没有明显的效果.

如何在测试失败时使用pytest报告我的输出capsys

flu*_*lub 12

capsys.readouterr()您使用捕获的输出时,您会看到正确的行为.因此,stdout和stderr的任何输出都将不再显示在测试报告中.但是,在此之后创建并且不消耗的任何新输出仍将被报告,因此您可以通过简单地将其再次写入输出流来获得报告中的完整输出:

def test_result_and_stdout(capsys):
    result = method_under_test()
    out, err = capsys.readouterr()
    sys.stdout.write(out)
    sys.stderr.write(err)
    assert out.startswith("Hello")
    assert result == 42
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的启示.我想,我不会在一段时间内想到这一点.我是否可以建议**(1)**澄清文件并**(2)**添加一个方法capsys.copyouterr()隐式执行此回写操作? (2认同)

Bru*_*ira 5

从文档中看,行为似乎是正确的:仅在测试函数(test_result_and_stdout)完成后,才恢复输出流,而不是在每次readouterr调用后恢复。我认为目前capsys除了捕获原始流外,还不支持将其重定向到原始流,这似乎是您想要的。

我建议在官方资料库中创建一个问题,看看人们怎么说。