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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM