Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python pytest capsys:检查输出并报告?_Python_Pytest - Fatal编程技术网

Python pytest capsys:检查输出并报告?

Python pytest capsys:检查输出并报告?,python,pytest,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 当作为python-m pytest myfile.py执行时, 将

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
当作为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 ===========================
这是一个非常好的特性。 但当我使用pytest的内置
capsys
fixture时,如下所示:

def test_result_and_stdout(capsys):
    result = method_under_test()
    out, err = capsys.readouterr()
    assert out.startswith("Hello")
    assert result == 42
报告不再包含实际输出:

================================== 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 ===========================
接下来,我查看了
CaptureFixture
类源代码 找到了一个很有前途的方法
close
(调用 一些
pop\u outerr\u to\u orig()
method), 但是在我的测试中调用
capsys.close()
也没有帮助, 根本没有明显的效果

如何让pytest在失败时报告输出
在使用
capsys

的测试中,从文档中可以看出,行为似乎是正确的:只有在test函数(
test\u result\u和stdout
)完成后,才会恢复输出流,而不是在每次
readouterr
调用之后。我不认为目前capsys除了捕获原始流之外还支持重定向到原始流,这似乎是您想要的


我建议您访问官方存储库,看看人们都说了些什么。

使用
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
使用“startswith”作为旁白。您也可以使用“in”关键字,例如:

    assert "Hello" in output
如果有大量数据被传递到stdout,这非常好,您可以使用“in”检查stdout中的不同行

def test_result_and_stdout(capsys):
    result = method_under_test()
    out, err = capsys.readouterr()
    sys.stdout.write(out)
    sys.stderr.write(err)
    assert "Hello" in out 
    assert result == 42
您还可以使用以下命令断言传递到stderr而不是stdout的内容:

    assert "What you are expecting" in err
另请注意,行:

    out, err = capsys.readouterr()

创建到目前为止对stdout和stderr的输出的快照,以便您能够断言您对该测试的期望。

正如@flub所描述的,在使用capsys时,捕捉并使用到stdout和stderr的输出,这是capsys的预期行为。如果希望在测试错误捕获中看到消息,可以在捕获消息后将它们写回stdout和stderr

但是,我发现一种常见的模式是在同一测试中串联运行两个命令,这通常是因为一个命令后的状态更改会影响下一个命令的行为。在测试详细输出时,您需要根据测试中特定命令的输出内容来测试,而不是测试期间运行的整个输出历史。为了将输出与单个命令隔离,您需要在调用命令之前以及之后捕获stdout/stderr。这样,在打印到独立命令的标准输出之前,您可以捕获并丢弃以前的标准输出内容

不幸的是,这不适合在捕获消息后将消息发送回stdout和stderr,因为如果这样做,它们将污染测试中下一个命令的输出

我的解决方案是创建一个helper函数,
recapsys
,它起到捕获并立即返回stdout/stderr内容的作用(如@flub所描述的)。此外,
recapsys
接受任意多个以前的捕获作为参数,并将在当前捕获之前反刍这些捕获。这样,您可以在调用测试中的命令之前捕获以前的stdout/stderr内容,然后在运行命令后打印出来

下面给出了recapsys的定义和用法示例。 (有关recapsys的基于类的实现,请查看。)

#测试内容_fn.py
导入系统
def recapsys(capsys,*捕获):
capture_now=capsys.readouterr()
对于captures+中的捕获(现在捕获,):
系统标准输出写入(捕获输出)
sys.stderr.write(capture.err)
现在就回来
def测试装置(capsys):
capture_pre=capsys.readouterr()#清除标准输出
msg=“生存还是毁灭,这是个问题:”
打印(msg)#执行方法(详细)
capture_post=recapsys(capsys,capture_pre)#捕获然后重新输出
断言capture_post.out==msg+“\n”#将输出与目标进行比较
capture_pre=capsys.readouterr()#清除标准输出
msg=“在心灵中,受苦是否更高尚”
打印(msg)#执行方法(详细)
capture_post=recapsys(capsys,capture_pre)#捕获然后重新输出
断言capture_post.out.lower().startswith(“是否”)#Test
capture_pre=capsys.readouterr()#清除标准输出
msg=“凶残命运的投石器和箭,”
打印(msg)#执行方法(详细)
capture_post=recapsys(capsys,capture_pre)#捕获然后重新输出
assert capture_post.out==“我们对爱并不陌生\n”#Test
test\u fn.py
上运行
pytest
会产生以下输出:

===================================== FAILURES ======================================
____________________________________ test_stdout ____________________________________

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

    def test_stdout(capsys):
        capture_pre = capsys.readouterr()  # Clear stdout
        msg = "To be, or not to be, that is the question:"
        print(msg)  # Execute method (verbose)
        capture_post = recapsys(capsys, capture_pre)  # Capture and then re-output
        assert capture_post.out == msg + "\n"  # Compare output to target
    
        capture_pre = capsys.readouterr()  # Clear stdout
        msg = "Whether 'tis nobler in the mind to suffer"
        print(msg)  # Execute method (verbose)
        capture_post = recapsys(capsys, capture_pre)  # Capture and then re-output
        assert capture_post.out.lower().startswith("whether")  # Test
    
        capture_pre = capsys.readouterr()  # Clear stdout
        msg = "The slings and arrows of outrageous fortune,"
        print(msg)  # Execute method (verbose)
        capture_post = recapsys(capsys, capture_pre)  # Capture and then re-output
>       assert capture_post.out == "We're no strangers to love\n"  # Test
E       assert 'The slings a...us fortune,\n' == "We're no strangers to love\n"
E         - We're no strangers to love
E         + The slings and arrows of outrageous fortune,

test_fn.py:30: AssertionError
------------------------------- Captured stdout call --------------------------------
To be, or not to be, that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
============================== short test summary info ==============================
FAILED test_fn.py::test_stdout - assert 'The slings a...us fortune,\n' == "We're n...
================================= 1 failed in 0.26s =================================
===========================================================================失败======================================
____________________________________测试____________________________________
capsys=
def测试装置(capsys):
capture_pre=capsys.readouterr()#清除标准输出
msg=“生存还是毁灭,这是个问题:”
打印(msg)#执行方法(详细)
capture_post=recapsys(capsys,capture_pre)#捕获然后重新输出
断言capture_post.out==msg+“\n”#将输出与目标进行比较
capture_pre=capsys.readouterr()#清除标准输出
msg=“在心灵中,受苦是否更高尚”
打印(msg)#执行方法(详细)
capture_post=recapsys(capsys,cap
===================================== FAILURES ======================================
____________________________________ test_stdout ____________________________________

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

    def test_stdout(capsys):
        capture_pre = capsys.readouterr()  # Clear stdout
        msg = "To be, or not to be, that is the question:"
        print(msg)  # Execute method (verbose)
        capture_post = recapsys(capsys, capture_pre)  # Capture and then re-output
        assert capture_post.out == msg + "\n"  # Compare output to target
    
        capture_pre = capsys.readouterr()  # Clear stdout
        msg = "Whether 'tis nobler in the mind to suffer"
        print(msg)  # Execute method (verbose)
        capture_post = recapsys(capsys, capture_pre)  # Capture and then re-output
        assert capture_post.out.lower().startswith("whether")  # Test
    
        capture_pre = capsys.readouterr()  # Clear stdout
        msg = "The slings and arrows of outrageous fortune,"
        print(msg)  # Execute method (verbose)
        capture_post = recapsys(capsys, capture_pre)  # Capture and then re-output
>       assert capture_post.out == "We're no strangers to love\n"  # Test
E       assert 'The slings a...us fortune,\n' == "We're no strangers to love\n"
E         - We're no strangers to love
E         + The slings and arrows of outrageous fortune,

test_fn.py:30: AssertionError
------------------------------- Captured stdout call --------------------------------
To be, or not to be, that is the question:
Whether 'tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
============================== short test summary info ==============================
FAILED test_fn.py::test_stdout - assert 'The slings a...us fortune,\n' == "We're n...
================================= 1 failed in 0.26s =================================