Pythonのプログラムにおいて、「特定の処理が正しくログを出力していることを確認したい」というときはありませんか?unittestのメソッドassertLogs()
はその疑問を解消するためのメソッドです。
ただ、日本語の利用例がなく、公式リファレンスももうちょっと分かりやすく書いて?な感じだったので、実動例を作ってみました。
assertLogs()
とは
with
文を利用するメソッドの一つで、with
文内で発生した、ログの出力を、指定のコンテキストマネージャオブジェクトに格納する というメソッドです。よって単体でアサート処理を行うわけではなく、別のassertXXX
メソッドと組み合わせて利用します。
import unittest
import logging
class Test_ProcessCaller(unittest.TestCase):
# ...
def test_processcaller_setlogger(self):
logger = logging.getLogger("TEST")
proc = ProcessCaller("python", "-V", logger=logger)
with self.assertLogs(logger=logger, level=logging.DEBUG) as cm:
proc.run()
self.assertEqual(cm.output, ['DEBUG:TEST:python -V'])
上記コードは、「ProcessCaller#run()
メソッドにおいて、デバッグレベルで呼び出したコマンドを出力することを確認する」というコードです。
with
文のexpressionで、assertLogs()
メソッドを呼び出すと、with
ブロック内でのログ出力がすべて、cm
変数に格納されます。`assertLogs()'の引数にロガーやログレベルを指定することで、収集するログを限定することができます。
そして、with
ブロックを抜けると、cm
変数にはoutput
とrecord
という二つのプロパティが設定されます。
- output:すべてのログを「画面に表示したときの文字列」の配列
- record:すべてのログを示す
record
オブジェクトの配列
これをassertEqual()
メソッドなどで期待した値と比較することで、「正しくログが出力されたか」を確認することができます。たとえば、上記のコードのProcessCaller
クラスのコンストラクタ引数からlogger
の指定を外すと・・・。
import unittest
import logging
class Test_ProcessCaller(unittest.TestCase):
# ...
def test_processcaller_setlogger(self):
logger = logging.getLogger("TEST")
proc = ProcessCaller("python", "-V")
with self.assertLogs(logger=logger, level=logging.DEBUG) as cm:
proc.run()
self.assertEqual(cm.output, ['DEBUG:TEST:python -V'])
一行目で作成したlogger
にはなにも出力されないため、テスト失敗となります。