pytest 测试输出和结果-捕获标准输出/标准错误输出

2022-03-29 17:25 更新

默认标准输出/标准错误/标准输入捕获行为

在测试执行期间,任何发送到 ​stdout和 ​stderr的输出都会被捕获。 如果测试或设置方法失败,其捕获的输出通常会与失败回溯一起显示。此行为可以通过 ​--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 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输出的一个主要好处是您可以使用打印语句进行调试:

# 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-7.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
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 0xdeadbeef0001>
========================= short test summary info ==========================
FAILED test_module.py::test_func2 - assert False
======================= 1 failed, 1 passed in 0.12s ========================

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

capsys​、​capsysbinary​、​capfd​和​capfbinary fixture​允许访问在测试执行期间创建的​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自己的每次测试捕获进行交互。

如果你想在文件描述符级别捕获,你可以使用​capfd fixture​,它提供了完全相同的接口,但也允许捕获库或子进程的输出,这些子进程直接写入操作系统级别的输出流(​FD1​和​FD2​)。

读取器的返回值变成了一个有两个属性的命名元组,​out​和​err​。

如果被测试的代码写入非文本数据,您可以使用​capsysbinary fixture​捕获它,而不是从​readouterr​方法返回字节。

如果被测试的代码写入非文本数据,您可以使用​capfbinary fixture​捕获它,而不是从​readouterr​方法返回字节。​capfbinary fixture​在文件描述符级别上操作。

为了在测试中暂时禁用捕获,​capsys​和​capfd​都有一个​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")


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号