次のような関数のテストを書いています:
def foo():
print 'hello world!'
したがって、この関数をテストする場合、コードは次のようになります。
import sys
from foomodule import foo
def test_foo():
foo()
output = sys.stdout.getline().strip() # because stdout is an StringIO instance
assert output == 'hello world!'
しかし、-s パラメータを指定して nosetests を実行すると、テストがクラッシュします。unittest または nose モジュールで出力をキャッチするにはどうすればよいでしょうか?
ベストアンサー1
私はこれを使うコンテキストマネージャー出力をキャプチャします。 最終的には、 を一時的に置き換えることによって、他の回答のいくつかと同じ手法を使用しますsys.stdout
。 コンテキスト マネージャーは、すべてのブックキーピングを 1 つの関数にラップするため、try-finally コードを書き直す必要がなく、このためだけにセットアップ関数とティアダウン関数を記述する必要もありません。
import sys
from contextlib import contextmanager
from StringIO import StringIO
@contextmanager
def captured_output():
new_out, new_err = StringIO(), StringIO()
old_out, old_err = sys.stdout, sys.stderr
try:
sys.stdout, sys.stderr = new_out, new_err
yield sys.stdout, sys.stderr
finally:
sys.stdout, sys.stderr = old_out, old_err
次のように使用します:
with captured_output() as (out, err):
foo()
# This can go inside or outside the `with` block
output = out.getvalue().strip()
self.assertEqual(output, 'hello world!')
さらに、ブロックを終了すると元の出力状態が復元されるためwith
、最初の関数と同じ関数内に 2 番目のキャプチャ ブロックを設定できます。これは、setup 関数と teardown 関数では不可能であり、try-finally ブロックを手動で記述すると冗長になります。この機能は、テストの目的が、2 つの関数の結果を、事前に計算された値ではなく、互いに対して比較することである場合に便利です。