ロギングを管理する方法

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} を介して無効にできます。 この引数は複数回渡すことができます:

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

さらに、次のオプションを使用して、失敗したテストでキャプチャされたコンテンツ (stdout、stderr、およびログ) のレポートを完全に無効にすることができます:

pytest --show-capture=no

caplog フィクスチャ

テスト内でキャプチャされたログメッセージのログレベルを変更することができます。 これは caplog フィクスチャによってサポートされています:

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

デフォルトでは、レベルはルートロガーに設定されていますが、便宜上、任意のロガーのログレベルを設定することもできます:

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

設定されたログレベルは、テストの終了時に自動的に復元されます。

コンテキストマネージャーを使用して、with ブロック内のログレベルを一時的に変更することもできます:

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

再び、デフォルトではルートロガーのレベルが影響を受けますが、代わりに任意のロガーのレベルを変更できます:

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

最後に、テスト実行中にロガーに送信されたすべてのログは、logging.LogRecord インスタンスと最終ログテキストの両方の形式でフィクスチャに利用可能になります。 これは、メッセージの内容をアサートしたい場合に便利です:

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

ログレコードのすべての利用可能な属性については、logging.LogRecord クラスを参照してください。

特定のメッセージが特定のロガー名の下で特定の重大度とメッセージでログに記録されていることを確認するだけでよい場合は、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 フェーズ内にはセットアップログのみが含まれ、call および teardown フェーズも同様です。

他のステージのログにアクセスするには、caplog.get_records(when) メソッドを使用します。 たとえば、特定のフィクスチャを使用するテストが警告をまったくログに記録しないことを確認したい場合、次のようにテアダウン中に setup および call ステージのレコードを検査できます:

@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 フィクスチャは、ルートロガーにハンドラを追加してログをキャプチャします。 たとえば、logging.config.dictConfig を使用してテスト中にルートロガーが変更された場合、このハンドラが削除され、ログがキャプチャされない可能性があります。 これを回避するには、ルートロガーの構成が既存のハンドラにのみ追加されることを確認してください。

ライブログ

log_cli 構成オプションを true に設定すると、pytest はログレコードを直接コンソールに出力します。

--log-cli-level を渡すことで、同等またはそれ以上のレベルのログレコードがコンソールに印刷されるログレベルを指定できます。 この設定は、logging's documentation に記載されているログレベル名または数値を受け入れます。

さらに、--log-cli-format および --log-cli-date-format を指定することもできます。 これらは、指定されていない場合は --log-format および --log-date-format を反映し、デフォルトになりますが、コンソールロギングハンドラにのみ適用されます。

すべての 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 と同じですが、ログファイルロギングハンドラに適用されます。

すべてのログファイルオプションは、構成 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 コマンドラインオプションで明示的に要求されない限り、変更されなくなりました。 これにより、ユーザーはロガーオブジェクトを自分で構成できます。 log_level を設定すると、グローバルにキャプチャされるレベルが設定されるため、特定のテストでこれより低いレベルが必要な場合は、caplog.set_level() 機能を使用してください。 そうしないと、そのテストは失敗しやすくなります。

  • Live Logs はデフォルトで無効になっており、log_cli 構成オプションを true に設定して有効にできます。 有効にすると、冗長性が増加し、各テストのロギングが表示されます。

  • Live Logs は現在 sys.stdout に送信され、動作するために -s コマンドラインオプションを必要としなくなりました。

バージョン 3.3 のロギング動作を部分的に復元したい場合は、次のオプションを ini ファイルに追加できます:

[pytest]
log_cli=true
log_level=NOTSET

この変更につながった議論の詳細については、#3013 を参照してください。