簡體   English   中英

如何查看 pytest 運行期間創建的正常打印輸出?

[英]How can I see normal print output created during pytest run?

有時我只想在我的代碼中插入一些打印語句,然后看看我在執行它時會打印出什么。 我常用的“鍛煉”方法是使用現有的 pytest 測試。 但是當我運行這些時,我似乎看不到任何標准輸出(至少在我的 IDE PyCharm 中)。

有沒有一種簡單的方法可以在 pytest 運行期間查看標准輸出?

-s開關禁用每次測試捕獲(僅當測試失敗時)。

-s相當於--capture=no

pytest 從單個測試中捕獲標准輸出並僅在某些條件下顯示它們,以及默認情況下打印的測試摘要。

可以使用“-r”選項顯示額外的摘要信息

pytest -rP

顯示已通過測試的捕獲輸出。

pytest -rx

顯示失敗測試的捕獲輸出(默認行為)。

輸出的格式使用 -r 比使用 -s 更漂亮。

在對已接受答案贊成評論中,問道:

有什么方法可以打印到控制台捕獲輸出以便它顯示在 junit 報告中?

在 UNIX 中,這通常稱為teeing 理想情況下, py.test 的默認設置是發球而不是捕獲。 非理想情況下,py.test 和任何現有的第三方 py.test 插件(我知道,無論如何)都不支持 teeing——盡管 Python 微不足道地支持 teeing out-of-the-box

Monkey-patching py.test 做任何不受支持的事情都是不平凡的。 為什么? 因為:

  • 大多數 py.test 功能被鎖定在打算從外部導入的私有_pytest包后面。 在不知道自己在做什么的情況下嘗試這樣做通常會導致公共pytest包在運行時引發晦澀的異常。 非常感謝,py.test。 真正強大的架構,你在那里。
  • 即使您確實知道如何以安全的方式對私有_pytest API 進行猴子修補,您也必須在運行由外部py.test命令運行的公共pytest之前這樣做。 不能在插件中執行此操作(例如,測試套件中的頂級conftest模塊)。 當 py.test 懶惰地開始動態導入你的插件時,任何你想要猴子補丁的 py.test 類早就被實例化了——你無法訪問那個實例。 這意味着,如果您希望有意義地應用猴子補丁,則不能再安全地運行外部py.test命令。 相反,您必須使用自定義 setuptools test命令來包裝該命令的運行,該命令(按順序):
    1. Monkey 修補私有_pytest API。
    2. 調用公共pytest.main()函數來運行py.test命令。

這個答案猴子補丁 py.test 的-s--capture=no選項來捕獲標准錯誤而不是標准輸出。 默認情況下,這些選項既不捕獲標准錯誤也不捕獲標准輸出。 當然,這並不完全是開球。 但每一次偉大的旅程都始於一個乏味的前傳,每個人都會在五年內忘記。

為什么要這樣做? 我現在告訴你。 我的 py.test 驅動的測試套件包含緩慢的功能測試。 顯示這些測試的標准輸出是有幫助和令人放心的,當另一個長時間運行的功能測試連續數周都沒有做任何事情時,可以防止leycec到達killall -9 py.test 但是,顯示這些測試的標准錯誤會阻止 py.test 報告測試失敗的異常回溯。 這是完全沒有幫助的。 因此,我們強制 py.test 捕獲 stderr 而不是stdout。

在我們開始之前,這個答案假設您已經有一個調用 py.test 的自定義 setuptools test命令。 如果您不這樣做,請參閱 py.test 編寫良好的良好實踐頁面的手動集成小節。

不要安裝pytest-runner ,第三方 setuptools 插件提供自定義 setuptools test命令也調用 py.test。 如果 pytest-runner 已經安裝,您可能需要卸載該 pip3 包,然后采用上面鏈接的手動方法。

假設您按照上面突出顯示的手動集成中的說明進行操作,您的代碼庫現在應該包含一個PyTest.run_tests()方法。 將此方法修改為類似於:

class PyTest(TestCommand):
             .
             .
             .
    def run_tests(self):
        # Import the public "pytest" package *BEFORE* the private "_pytest"
        # package. While importation order is typically ignorable, imports can
        # technically have side effects. Tragicomically, that is the case here.
        # Importing the public "pytest" package establishes runtime
        # configuration required by submodules of the private "_pytest" package.
        # The former *MUST* always be imported before the latter. Failing to do
        # so raises obtuse exceptions at runtime... which is bad.
        import pytest
        from _pytest.capture import CaptureManager, FDCapture, MultiCapture

        # If the private method to be monkey-patched no longer exists, py.test
        # is either broken or unsupported. In either case, raise an exception.
        if not hasattr(CaptureManager, '_getcapture'):
            from distutils.errors import DistutilsClassError
            raise DistutilsClassError(
                'Class "pytest.capture.CaptureManager" method _getcapture() '
                'not found. The current version of py.test is either '
                'broken (unlikely) or unsupported (likely).'
            )

        # Old method to be monkey-patched.
        _getcapture_old = CaptureManager._getcapture

        # New method applying this monkey-patch. Note the use of:
        #
        # * "out=False", *NOT* capturing stdout.
        # * "err=True", capturing stderr.
        def _getcapture_new(self, method):
            if method == "no":
                return MultiCapture(
                    out=False, err=True, in_=False, Capture=FDCapture)
            else:
                return _getcapture_old(self, method)

        # Replace the old with the new method.
        CaptureManager._getcapture = _getcapture_new

        # Run py.test with all passed arguments.
        errno = pytest.main(self.pytest_args)
        sys.exit(errno)

要啟用此猴子補丁,請按如下方式運行 py.test:

python setup.py test -a "-s"

現在將捕獲 Stderr 但不是stdout。 漂亮!

將上面的猴子補丁擴展到 tee stdout 和 stderr 留給讀者作為練習,並有大量空閑時間。

運行測試時使用-s選項。 運行測試時, exampletest.py中的所有打印語句都將打印在控制台上。

py.test exampletest.py -s

根據pytest 文檔,pytest 版本 3 可以在測試中臨時禁用捕獲:

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

最近添加了pytest --capture=tee-sys ( v5.4.0 )。 您可以捕獲並查看 stdout/err 上的輸出。


嘗試pytest -s -v test_login.py在控制台中獲取更多信息。

-v這是一個簡短的--verbose

-s表示“禁用所有捕獲”



您還可以通過在項目根目錄中的pytest.initox.ini中設置以下內容來啟用實時日志記錄

[pytest]
log_cli = True

或者直接在cli上指定

pytest -o log_cli=True
pytest test_name.py -v -s

簡單的!

我建議使用 -h 命令。 可能會使用一些非常有趣的命令。 但是,對於這種特殊情況: -s快捷方式為 --capture=no。 足夠的

pytest <test_file.py> -s

如果您使用的是 PyCharm IDE,那么您可以使用運行工具欄運行單個測試或所有測試。 運行工具窗口顯示應用程序生成的輸出,您可以在其中看到所有打印語句作為測試輸出的一部分。

如果您使用logging ,除了-s用於通用標准輸出之外,您還需要指定打開日志輸出。 基於pytest 測試中的日志記錄,我正在使用:

pytest --log-cli-level=DEBUG -s my_directory/

如果有人想從帶有輸出的代碼運行測試:

if __name__ == '__main__':
    pytest.main(['--capture=no'])

capsys、capsysbinary、capfd 和 capfdbinary 夾具允許訪問在測試執行期間創建的 stdout/stderr 輸出。 這是一個執行一些輸出相關檢查的示例測試函數:

def test_print_something_even_if_the_test_pass(self, capsys):
    text_to_be_printed = "Print me when the test pass."
    print(text_to_be_printed)
    p_t = capsys.readouterr()
    sys.stdout.write(p_t.out)
    # the two rows above will print the text even if the test pass.

結果如下:

test_print_something_even_if_the_test_pass PASSED [100%]當測試通過時打印我。

其他答案不起作用。 查看捕獲的輸出的唯一方法是使用以下標志:

pytest - 顯示全部捕獲

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM