Python で標準出力される文字列のテストをすることを考えます。
class Hoge(): def __init__(self, name): self.name = name def hoge(self): print(self.name)
例えば、この Hoge クラスの hoge メソッドをテストするとしましょう。
print にパッチを当てる
Python3 に標準で入っている unittest の patch を使います。
class TestHoge(TestCase): @patch('test_stdout.print') def test_hoge1(self, _print): hoge = Hoge('hoge') hoge.hoge() expected = call('hoge') actual = _print.call_args self.assertEqual(expected, actual)
このような形で組み込み関数の print 関数にモックオブジェクトをパッチします。 このようにすることで、標準出力そのものではありませんが、 print に渡された値を取得することが出来るので、その値をチェックします。
sys.stdout にパッチを当てる
もうちょっと直接的に標準出力の値を取得することを考えます。 先ほどは print 関数にパッチを当てましたが、今度は sys.stdout にパッチしてみましょう。
class TestHoge(TestCase): @patch('sys.stdout') def test_hoge2(self, _stdout): hoge = Hoge('hoge') hoge.hoge() expected = [ call('hoge'), call('\n') ] actual = _stdout.write.call_args_list self.assertEqual(expected, actual)
実際にテストしてみると、一度の print の呼び出しで sys.stdout.write は改行の表示のために二度呼び出されていることが分かりました。
sys.stdout がどのように扱われるかは print の実装に依存しています。 今は print の実装をテストしているわけではないので、この方法で値を取得すべきではないでしょう。
test.support を使う
上で紹介した方法以外で何か良い方法がないか探したところ、下の記事を見つけました。
test.support モジュールに captured_stdout という標準出力をキャプチャする機能が含まれているみたいです。
このモジュールにはほかにもいろいろ使えそうな機能が含まれているようなので、機会があればちゃんと使ってみたいです。
まとめ
captured_stdout を使うと、より直接的に標準出力される値を取得出そうなことがわかりました。 でも実際のところ、一つ目に示した print にパッチを当てるだけで充分な場合が多いんじゃないかなと思います。
今回使用したコードの全体は下のリンク先に置いてます。