ロガーからの出力が実際に期待する形式(つまり、logging.basicConfig()の呼び出しによって設定される)であることをテストするユニットテストをPythonでどのように作成できますか?カスタムStreamHandlerと「re」ライブラリの使用に沿って考えていますが、StreamHandler.emit()に渡されたLogRecordが出力される文字列を提供できるようには見えません。
2 に答える
ドキュメント(http://packages.python.org/testfixtures/logging.html)から:
これを支援するために、TestFixturesを使用すると、Pythonのロギングフレームワークへの呼び出しの出力を簡単にキャプチャして、期待どおりであることを確認できます。作成するテストのタイプに応じて、3つの異なる手法があります。
例はドキュメントに含まれています。短縮版は以下の通りです。
コンテキストマネージャー
>>> import logging
>>> from testfixtures import LogCapture
>>> with LogCapture() as l:
... logger = logging.getLogger()
... logger.info('a message')
... logger.error('an error')
その後、ログが等しいかどうかを確認できます。
>>> l.check(
... ('root', 'INFO', 'a message'),
... ('root', 'ERROR', 'another error'),
... )
Traceback (most recent call last):
...
AssertionError: Sequence not as expected:
same:
(('root', 'INFO', 'a message'),)
first:
(('root', 'ERROR', 'another error'),)
second:
(('root', 'ERROR', 'an error'),)
デコレータ
前と同様ですが、特定の機能に適用されます。
from testfixtures import log_capture
@log_capture()
def test_function(l):
logger = logging.getLogger()
logger.info('a message')
logger.error('an error')
l.check(
('root', 'INFO', 'a message'),
('root', 'ERROR', 'an error'),
)
手動使用
>>> from testfixtures import LogCapture
>>> l = LogCapture()
その後、ログを「チェック」することもできます。
>>> l.check(('root', 'INFO', 'a message'))
<...>
編集:特定のログにアクセスしてカスタムの方法で分析するには、繰り返し処理してl.records
(ここでl
は、インスタンスだけですLogCapture
)、各ログのいくつかのプロパティにアクセスできます(たとえばmsg
、ロガーに送信されたメッセージをlevelname
含み、レベルのコードネームを含みます、そして他にもたくさんのプロパティがあります)。
標準ライブラリのみを使用する場合は、このソリューションが役立ちます。unittest
これは、mock
ライブラリに基づいています。
たとえばscript.py
、次のコンテンツがある場合。
logger = logging.getLogger(__name__)
def log_something():
logger.debug("something")
次のようなテストを作成できます。
import unittest
import mock
from script import log_something
@mock.patch("script.logger")
def test_function(mock_log):
log_something()
assertTrue(
"something" in mock_log.debug.call_args_list[0][0][0]
)
これは、ライブラリのcall_args_listmock
を使用しています。
[0][0][0]
最後に説明するには:
はオブジェクト
call_args_list
のリストで、次のようになります。したがって、最初は最初のオブジェクトを返します。call
[call("something")]
[0]
call
2番目は、オブジェクト
[0]
の引数のタプルを返します。call
このようになります("something",)
。Thirdは、この場合
[0]
に与えられた最初の引数を返しますlogger
。したがって、最終的な文字列は。のみになります"something"
。