LoginSignup
6
2

More than 3 years have passed since last update.

Pythonのunittestでの、assertLogs()の使い方

Posted at

Pythonのプログラムにおいて、「特定の処理が正しくログを出力していることを確認したい」というときはありませんか?unittestのメソッドassertLogs()はその疑問を解消するためのメソッドです。

ただ、日本語の利用例がなく、公式リファレンスももうちょっと分かりやすく書いて?な感じだったので、実動例を作ってみました。

assertLogs()とは

with文を利用するメソッドの一つで、with文内で発生した、ログの出力を、指定のコンテキストマネージャオブジェクトに格納する というメソッドです。よって単体でアサート処理を行うわけではなく、別のassertXXXメソッドと組み合わせて利用します。

test_XXX.py
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変数にはoutputrecordという二つのプロパティが設定されます。

  • output:すべてのログを「画面に表示したときの文字列」の配列
  • record:すべてのログを示すrecordオブジェクトの配列

これをassertEqual()メソッドなどで期待した値と比較することで、「正しくログが出力されたか」を確認することができます。たとえば、上記のコードのProcessCallerクラスのコンストラクタ引数からloggerの指定を外すと・・・。

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

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2