pytest:捕获 STDOUT/STDERR 输出
一、默认的 stdout/stderr/stdin 捕捉行为
在测试执行的过程中,很多输出被 stdout 和 stderr 捕获。当一个测试或者setup方法失败的时候,相关的输出经常会与错误跟踪( failure traceback)一起显示。(这个行为可以被命令行中 --show-capture 选项配置)。
另外,如果从stdin中读取失败了,它将会被设置为“null”,因为在自动化测试中,我们几乎不可能等待一个交互式的输入。
二、设置捕捉方法或禁用捕捉
在pytest中有三种执行捕获的方式:
- fd (文件描述符)级别的捕捉(默认):所有对文件系统描述符 1 和 2 的写入会被抓取
- sys 级别捕捉:只有在python文件中写 sys.stdout 和 sys.stderr 的会被抓取。向文件描述符的写入操作不会被抓取
- tee-sys 捕捉:python中的 sys.stdout 和 sys.stderr 会被抓取,写入也会通过真实系统的 sys.stdout 和 sys.stderr。这允许输出被“实时打印”,被插件用的较多,例如 junitxml
你可以通过命令行来修改输出的机制:
pytest -s # 禁用所有的抓取
pytest --capture=sys # 使用python文件中的 sys.stdout/stderr 替换原有的标准输出
pytest --capture=fd # 也输出标准输出和标准错误输出
pytest --capture=tee-sys # 结合了 'sys' 和 '-s',抓取 sys.stdout/stderr 然后传递给真实的标准输出
三、使用print来调试
def setup_func(function):
print("setting up", function)
def test_func1():
assert True
def test_func2():
assert False
运行此模块将精确显示失败函数的输出
D:\pytest\learn01\a>pytest -s -v test_std.py
========================================================================================== test session starts ===========================================================================================
platform win32 -- Python 3.7.3, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- d:\python3.7\python\python3.exe
cachedir: .pytest_cache
rootdir: D:\pytest\learn01, configfile: pytest.ini
collected 2 items
test_std.py::test_func1 PASSED
test_std.py::test_func2 FAILED
=========================================== FAILURES ===========================================
___________________________________________ test_func2 ___________________________________________
def test_func2():
> assert False
E assert False
test_std.py:8: AssertionError
============================================= short test summary info =============================================
FAILED test_std.py::test_func2 - assert False
====================================== 1 failed, 1 passed in 0.16s =======================================
四、在测试方法中访问标准输出
capsys, capsysbinary, capfd, 和capfdbinary 四个夹具允许我们在测试执行的时候访问 stdout/stderr 的输出。下面是一些执行输出检查的例子:
def test_output(capsys):
print("hello world")
sys.stderr.write('hello erro')
output=capsys.readouterr()
assert output.out == "hello world\n"
assert output.err == "hello erro"
print('next')
output = capsys.readouterr()
assert output.out=='next\n'
readouterr() 获取了标准输出当前状态的快照,并且会继续捕获。在测试函数完成之后,原始的输出流会被恢复。使用 capsys 这种方法使得我们不需要关注获取输出流和在测试之后重置输出流,同时与pytest自身的捕获机制兼容良好。 如果你想在文件描述符的层面进行捕获,你可以使用 capfd夹具,这个夹具的使用方法与上面介绍的相同,同时也允许从库中或子进程中抓取那些直接写入操作系统的输出流。 readouterr的返回值改变为两个属性的元组,out和err。 如果测试中写入的数据不是文本类型(non-textual)的,你也可以使用capsysbinary来捕获二进制数据,readouterr方法返回一个bytes。 如果测试中写入的数据不是文本类型(non-textual)的,你也可以使用capfdbinary来捕获二进制数据,readouterr方法返回一个bytes。capfdbinary夹具是作用在文件描述符层面。
为了在一个测试中暂时的禁用捕获器,capsys和capfd都拥有一个 disabled() 方法,我们可以使用一个上下文管理器去在某一块中禁用捕
def test_disabling_capturing(capsys):
print("this output is captured")
with capsys.disabled():
print("output not captured, going directly to sys.stdout")
print("this output is also captured")
D:\pytest\learn01\a>pytest test_std.py
=========================== test session starts ============================
platform win32 -- Python 3.7.3, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: D:\pytest\learn01, configfile: pytest.ini
collected 1 item
test_std.py output not captured, going directly to sys.stdout
. [100%]
=================================== 1 passed in 0.09s ====================================
- 下一篇:pytest:临时目录和文件
- 上一篇:pytest–警告捕捉