捕获stdout/stderr输出

默认stdout/stderr/stdin捕获行为

在测试执行期间,任何输出发送到 stdoutstderr 被捕获。如果测试或设置方法失败,则通常会显示相应的捕获输出以及失败跟踪。(此行为可以通过 --show-capture 命令行选项)。

此外, stdin 设置为“空”对象,该对象在尝试读取时将失败,因为在运行自动测试时很少需要等待交互式输入。

默认情况下,捕获是通过截取对低级文件描述符的写操作来完成的。这允许捕获简单打印语句的输出以及由测试启动的子进程的输出。

设置捕获方法或禁用捕获

有三种方法 pytest 可以执行捕获:

  • fd (文件描述符)级别捕获(默认):将捕获到操作系统文件描述符1和2的所有写入。

  • sys 级别捕获:仅写入python文件 sys.stdoutsys.stderr 将被捕获。不捕获对文件描述符的写入。

  • tee-sys 捕获:Python写入 sys.stdoutsys.stderr 将被捕获,但是写入也将传递到实际 sys.stdoutsys.stderr . 这允许输出被“实时打印”并捕获以供插件使用,例如junitxml(pytest 5.4中的新功能)。

您可以从命令行影响输出捕获机制:

pytest -s                  # disable all capturing
pytest --capture=sys       # replace sys.stdout/stderr with in-mem files
pytest --capture=fd        # also point filedescriptors 1 and 2 to temp file
pytest --capture=tee-sys   # combines 'sys' and '-s', capturing sys.stdout/stderr
                           # and passing it along to the actual sys.stdout/stderr

使用打印语句进行调试

默认捕获stdout/stderr输出的一个主要好处是可以使用print语句进行调试:

# content of test_module.py


def setup_function(function):
    print("setting up", function)


def test_func1():
    assert True


def test_func2():
    assert False

运行此模块将精确显示失败函数的输出,并隐藏另一个:

$ pytest
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 2 items

test_module.py .F                                                    [100%]

================================= FAILURES =================================
________________________________ test_func2 ________________________________

    def test_func2():
>       assert False
E       assert False

test_module.py:12: AssertionError
-------------------------- Captured stdout setup ---------------------------
setting up <function test_func2 at 0xdeadbeef>
========================= short test summary info ==========================
FAILED test_module.py::test_func2 - assert False
======================= 1 failed, 1 passed in 0.12s ========================

从测试函数访问捕获的输出

这个 capsyscapsysbinarycapfdcapfdbinary fixtures允许访问在测试执行期间创建的stdout/stderr输出。下面是一个示例测试函数,它执行一些与输出相关的检查:

def test_myoutput(capsys):  # or use "capfd" for fd-level
    print("hello")
    sys.stderr.write("world\n")
    captured = capsys.readouterr()
    assert captured.out == "hello\n"
    assert captured.err == "world\n"
    print("next")
    captured = capsys.readouterr()
    assert captured.out == "next\n"

这个 readouterr() 调用快照到目前为止的输出-捕获将继续进行。测试函数完成后,将恢复原始流。使用 capsys 通过这种方式,您的测试不必关心设置/重置输出流,并且还可以与Pytest自己的每个测试捕获进行良好的交互。

如果要在FileDescriptor级别捕获,可以使用 capfd fixture提供完全相同的接口,但也允许从库或直接写入操作系统级输出流(FD1和FD2)的子进程中捕获输出。

返回值来自 readouterr 改为A namedtuple 有两个属性, outerr .

如果测试中的代码写入非文本数据,则可以使用 capsysbinary 代替返回的装置 bytesreadouterr 方法。

如果测试中的代码写入非文本数据,则可以使用 capfdbinary 代替返回的装置 bytesreadouterr 方法。这个 capfdbinary fixture在filedescriptor级别上运行。

临时禁用测试中的捕获 capsyscapfd 有一个 disabled() 可以用作上下文管理器的方法,在 with

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")