如何管理日誌記錄

pytest 自動捕獲日誌級別為 WARNING 或更高級別的日誌消息,並以與捕獲的 stdout 和 stderr 相同的方式在每個失敗測試的單獨部分中顯示它們。

無選項運行

pytest

像這樣顯示失敗的測試

----------------------- Captured stdlog call ----------------------
test_reporting.py    26 WARNING  text going to logger
----------------------- Captured stdout call ----------------------
text going to stdout
----------------------- Captured stderr call ----------------------
text going to stderr
==================== 2 failed in 0.02 seconds =====================

默認情況下,每個捕獲的日誌消息都顯示模組、行號、日誌級別和消息。

如果需要,可以通過傳遞特定的格式化選項,將日誌和日期格式指定為日誌記錄模組支持的任何格式

pytest --log-format="%(asctime)s %(levelname)s %(message)s" \
        --log-date-format="%Y-%m-%d %H:%M:%S"

像這樣顯示失敗的測試

----------------------- Captured stdlog call ----------------------
2010-04-10 14:48:44 WARNING text going to logger
----------------------- Captured stdout call ----------------------
text going to stdout
----------------------- Captured stderr call ----------------------
text going to stderr
==================== 2 failed in 0.02 seconds =====================

這些選項也可以通過 pytest.ini 文件自定義

[pytest]
log_format = %(asctime)s %(levelname)s %(message)s
log_date_format = %Y-%m-%d %H:%M:%S

可以通過 --log-disable={logger_name} 禁用特定的 logger。此參數可以多次傳遞

pytest --log-disable=main --log-disable=testing

此外,可以使用以下命令完全禁用失敗測試中捕獲內容(stdout、stderr 和日誌)的報告

pytest --show-capture=no

caplog fixture

在測試中,可以更改捕獲的日誌消息的日誌級別。這由 caplog fixture 支持

def test_foo(caplog):
    caplog.set_level(logging.INFO)

默認情況下,級別設置在 root logger 上,但是為了方便起見,也可以設置任何 logger 的日誌級別

def test_foo(caplog):
    caplog.set_level(logging.CRITICAL, logger="root.baz")

設置的日誌級別在測試結束時自動恢復。

也可以使用上下文管理器在 with 塊中臨時更改日誌級別

def test_bar(caplog):
    with caplog.at_level(logging.INFO):
        pass

同樣,默認情況下 root logger 的級別會受到影響,但是可以使用以下方法更改任何 logger 的級別

def test_bar(caplog):
    with caplog.at_level(logging.CRITICAL, logger="root.baz"):
        pass

最後,測試運行期間發送到 logger 的所有日誌都以 logging.LogRecord 實例和最終日誌文本的形式在 fixture 中提供。當您想要斷言消息的內容時,這很有用

def test_baz(caplog):
    func_under_test()
    for record in caplog.records:
        assert record.levelname != "CRITICAL"
    assert "wally" not in caplog.text

有關日誌記錄的所有可用屬性,請參閱 logging.LogRecord 類。

如果您只想確保某些消息已使用給定的嚴重程度和消息在給定的 logger 名稱下記錄,您也可以使用 record_tuples

def test_foo(caplog):
    logging.getLogger().info("boo %s", "arg")

    assert caplog.record_tuples == [("root", logging.INFO, "boo arg")]

您可以調用 caplog.clear() 來重置測試中捕獲的日誌記錄

def test_something_with_clearing_records(caplog):
    some_method_that_creates_log_records()
    caplog.clear()
    your_test_method()
    assert ["Foo"] == [rec.message for rec in caplog.records]

caplog.records 屬性僅包含當前階段的記錄,因此在 setup 階段中,它僅包含 setup 日誌,callteardown 階段也是如此。

要訪問其他階段的日誌,請使用 caplog.get_records(when) 方法。 例如,如果您想確保使用特定 fixture 的測試永遠不會記錄任何警告,則可以在 teardown 期間檢查 setupcall 階段的記錄,如下所示

@pytest.fixture
def window(caplog):
    window = create_window()
    yield window
    for when in ("setup", "call"):
        messages = [
            x.message for x in caplog.get_records(when) if x.levelno == logging.WARNING
        ]
        if messages:
            pytest.fail(f"warning messages encountered during testing: {messages}")

完整的 API 可在 pytest.LogCaptureFixture 找到。

警告

caplog fixture 向 root logger 添加一個 handler 以捕獲日誌。如果在測試期間修改了 root logger,例如使用 logging.config.dictConfig,則此 handler 可能會被刪除,並導致無法捕獲任何日誌。 為避免這種情況,請確保任何 root logger 配置僅添加到現有的 handlers。

實時日誌

通過將 log_cli 配置選項設置為 true,pytest 將在日誌記錄發出時直接將其輸出到控制台。

您可以通過傳遞 --log-cli-level 來指定日誌級別,對於該級別,將級別等於或高於該級別的日誌記錄打印到控制台。 此設置接受日誌級別名稱或數值,如 logging’s documentation 中所示。

此外,您還可以指定 --log-cli-format--log-cli-date-format,如果未提供,它們將鏡像並默認設置為 --log-format--log-date-format,但僅適用於控制台日誌記錄 handler。

所有 CLI 日誌選項也可以在配置 INI 文件中設置。 選項名稱是

  • log_cli_level

  • log_cli_format

  • log_cli_date_format

如果您需要將整個測試套件日誌記錄調用記錄到文件中,則可以傳遞 --log-file=/path/to/log/file。 此日誌文件默認以寫模式打開,這意味著它將在每次運行測試會話時被覆蓋。 如果您希望以追加模式打開文件,則可以傳遞 --log-file-mode=a。 請注意,日誌文件位置的相對路徑,無論是在 CLI 上傳遞還是在配置文件中聲明,始終相對於當前工作目錄解析。

您還可以通過傳遞 --log-file-level 來指定日誌文件的日誌記錄級別。 此設置接受日誌級別名稱或數值,如 logging’s documentation 中所示。

此外,您還可以指定 --log-file-format--log-file-date-format,它們等於 --log-format--log-date-format,但適用於日誌文件日誌記錄 handler。

所有日誌文件選項也可以在配置 INI 文件中設置。 選項名稱是

  • log_file

  • log_file_mode

  • log_file_level

  • log_file_format

  • log_file_date_format

您可以調用 set_log_path() 以動態自定義 log_file 路徑。 此功能被認為是實驗性的。 請注意,set_log_path() 遵循 log_file_mode 選項。

自定義顏色

如果啟用了彩色終端輸出,則日誌級別會被著色。 通過 add_color_level() 支持從默認顏色更改或將顏色添加到自定義日誌級別。 例子

@pytest.hookimpl(trylast=True)
def pytest_configure(config):
    logging_plugin = config.pluginmanager.get_plugin("logging-plugin")

    # Change color on existing log level
    logging_plugin.log_cli_handler.formatter.add_color_level(logging.INFO, "cyan")

    # Add color to a custom log level (a custom log level `SPAM` is already set up)
    logging_plugin.log_cli_handler.formatter.add_color_level(logging.SPAM, "blue")

警告

此功能及其 API 被認為是實驗性的,並且可能會在發布之間更改,恕不另行通知。

發布說明

此功能作為 pytest-catchlog 插件的直接替代品引入,它們彼此衝突。 當引入此功能時,已刪除與 pytest-capturelog 的向後兼容性 API,因此如果因此您仍然需要 pytest-catchlog,則可以通過添加到 pytest.ini 來禁用內部功能

[pytest]
    addopts=-p no:logging

pytest 3.4 中的不兼容更改

此功能在 3.3 中引入,並且在收到社區反饋後,在 3.4 中進行了一些不兼容的更改

  • 除非通過 log_level 配置或 --log-level 命令行選項顯式請求,否則不再更改日誌級別。 這允許用戶自行配置 logger 對象。 設置 log_level 將設置全局捕獲的級別,因此如果特定測試需要低於此級別的級別,請使用 caplog.set_level() 功能,否則該測試很容易失敗。

  • 實時日誌 現在默認禁用,可以通過將 log_cli 配置選項設置為 true 來啟用。 啟用後,詳細程度會增加,因此每個測試的日誌記錄都是可見的。

  • 實時日誌 現在發送到 sys.stdout,不再需要 -s 命令行選項才能工作。

如果您想部分恢復版本 3.3 的日誌記錄行為,您可以將此選項添加到您的 ini 文件中

[pytest]
log_cli=true
log_level=NOTSET

有關導致這些更改的討論的更多詳細信息,請參閱 #3013