7、pytest -- 捕獲標準輸出和標準錯誤輸出

1. 標準輸出/標準錯誤輸出/標準輸入的默認捕獲行爲

在測試執行期間,任何標準輸出和標準錯誤輸出都將會被捕獲;如果測試失敗或者發生異常,異常信息的堆棧也將一同顯示,你可以通過--show-capture命令行選項來自定義這些行爲;

--show-capture的配置項可以爲:no,stdout,stderr,log,all,默認是all

另外,標準輸入被設置爲一個"null"對象。因爲在自動化測試中,很少需要使用到交互輸入的場景;

實際上,當我們想要使用標準輸入時,會得到一個錯誤:OSError: reading from stdin while output is captured

通常情況下,捕獲行爲是通過攔截對低級別文件描述符的寫入操作來實現的。這就使得我們可以捕獲簡單的print()語句以及測試中子程序的輸出行爲;

2. 修改和去使能捕獲行爲

pytest有兩種捕獲行爲,可以通過--capture命令行選項來指定;

2.1. 文件描述符級別的捕獲行爲(默認)

所有向操作系統的文件描述符1(標準輸入)和2(標準錯誤輸入)的寫入行爲都會被捕獲,這個也是pytest的默認捕獲行爲,也可以通過--capture=fd來指定;

文件描述符是與當前進程打開的文件相對應的小整數。例如,標準輸入的文件描述符通常是0,標準輸出的是1,標準錯誤的是2,之後被進程打開的文件的描述符依次指定爲3、4、5等。

2.2. sys級別的捕獲行爲

只有向Pythonsys.stdoutsys.stderr的寫入行爲會被捕獲,不執行對文件描述符的寫入的捕獲,通過--capture=sys來指定;

2.3. 去使能捕獲行爲

通過--capture=no可以去使能pytest的捕獲行爲;

也可以通過-s命令行選項實現相同的效果,它只是--capture=no的一個快捷方式,本質上是一樣的;

3. 使用print()函數調試用例

默認的捕獲行爲帶來的一個主要的好處是,就是可以使用print()函數幫助調試用例;

我們來看下面這個例子:

# src/chapter-7/test_module.py

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


def test_func1():
    assert True


def test_func2():
    assert False

setup_function(function)函數會在每個測試用例開始之前執行,做一些初始化的操作;

現在,我們來執行這個模塊:

λ pipenv run pytest -q src/chapter-7/test_module.py
.F                                                      [100%] 
========================== FAILURES ========================== 
_________________________ test_func2 _________________________

    def test_func2():
>       assert False
E       assert False

src\chapter-7\test_module.py:32: AssertionError
------------------- Captured stdout setup -------------------- 
setting up <function test_func2 at 0x000001F35E76C158>
1 failed, 1 passed in 0.05s

可以看到,pytest會把失敗的用例信息精確的打印出來,並且會忽略其他的用例;

4. 在測試用例中訪問捕獲到的信息

我們可以通過capsyscapsysbinarycapfdcapfdbinary fixtures來訪問測試執行過程中產生的輸出信息;

下面這個例子用於檢查測試中的輸出信息:

# src/chapter-7/test_output.py

import sys


def test_output(capsys):
    print('hello')
    print('world', file=sys.stderr, end='&')  # 標準錯誤輸出,修改結束符
    captured = capsys.readouterr()
    assert captured.out == 'hello\n'  # print() 默認的結束符是換行符
    assert captured.err == 'world&'
    print('next')
    captured = capsys.readouterr()
    assert captured.out == 'next\n'

readouterr()方法會返回一個命名元組(包含outerr屬性),表示到目前爲止所有的標準輸出和標準錯誤輸出,然後重置緩存區

如果你想訪問文件描述符級別的測試輸出,可以使用capfd fixture,它提供了完全相同的接口;

如果想訪問的是非文本型的數據,可以使用capsysbinary fixture,它的readouterr()方法返回的是字節流,參考下面的例子:

# src/chapter-7/test_output.py

def test_binary_output(capsysbinary):
    print('hello')
    captured = capsysbinary.readouterr()
    assert captured.out == b'hello\n'

如果你想臨時的去使能捕獲行爲,可以使用capsys.disabled()方法,它作爲一個上下文管理器來使用,可以禁止with作用域中的捕獲行爲,參考下面的例子:

# src/chapter-7/test_output.py

def test_disabling_capturing(capsys):
    print("hello")
    with capsys.disabled():
        print("world")
    captured = capsys.readouterr()
    assert captured.out == "hello\n"

GitHub倉庫地址:https://github.com/luizyao/pytest-chinese-doc

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章