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にはなにも出力されないため、テスト失敗となります。