tl;dr
- 出力する文字列を生成する関数を作り、そのテストを書くべきだと私は思う
sys.stdout
をキャプチャすれば表示内容のテストが書けるtest.support.capture_stdout()
コンテクストマネージャを使うべき- そもそも unittest でやるべきではない
はじめに
いろいろな環境があります。ほとんど標準ライブラリしか使えないとか、莫大な量の print
があるとか、いろいろあります。
我々はそういった環境においてもやっていくことになります。したがって、やっていきましょう。
暗黙のうちに Python 3.5 以降を前提としています。
sys.stdout
をキャプチャする
コード
import sys from io import StringIO io = StringIO() # 標準出力を io に結びつける sys.stdout = io print('hoge') # 標準出力を元に戻す sys.stdout = sys.__stdout__ print('captured: {}'.format(io.getvalue())) # captured: hoge\n
解説
ご存知の通り、UNIX 世界において標準出力はファイルです。そして、Python においてもそうです。
さらに、Python にはファイルを模倣したようなオブジェクトが用意されています。それが io.StringIO
です。
これを sys.stdout
に放り込めば、標準出力を変数にリダイレクトするといったことができます。
import sys from io import StringIO io = StringIO() sys.stdout = io
さてあとは普段通りに print
するだけです。そうすると、io
に、出力されるはずだった文字列が蓄積されていきます。
print('this') print('is') print('test')
満足しましたか? それでは io
に蓄積されたものを見ていきましょう。おっと sys.stdout
を元の標準出力に戻すことを忘れずに。
sys.stdout = sys.__stdout__ print('captured: {}'.format(io.getvalue()))
sys.__stdout__
には、プログラム起動時の標準出力を示すオブジェクトが格納されています。
こうして、我々は標準出力に表示される内容をキャプチャする方法を知りました。
標準出力に表示される内容のテストを書く
コード
import sys def method_one(): print('called method_one()') def method_two(): print('called method_two()') print('not captured', file=sys.stderr)
import sys import unittest import hoge from io import StringIO class HogeTest(unittest.TestCase): def setUp(self): self.captor = StringIO() sys.stdout = self.captor def tearDown(self): sys.stdout = sys.__stdout__ def test_method_one(self): hoge.method_one() self.assertEqual(self.captor.getvalue(), 'called method_one()\n') def test_method_two(self): hoge.method_two() self.assertEqual(self.captor.getvalue(), 'called method_two()\n') if __name__ == '__main__': unittest.main()
解説
さて、キャプチャされた文字列を取得する方法まで分かれば、あとは unittest の流儀に沿って書いていけばよいです。 改行コードのことだけ忘れないように!
まとめ
もっとテストの書きやすい設計にしてくれ