関数foo
はコンソールに出力します。コンソールの印刷をテストしたい。 Pythonでこれをどのように達成できますか?
この関数をテストする必要があり、returnステートメントはありません:
def foo(inStr):
print "hi"+inStr
私のテスト:
def test_foo():
cmdProcess = subprocess.Popen(foo("test"), stdout=subprocess.PIPE)
cmdOut = cmdProcess.communicate()[0]
self.assertEquals("hitest", cmdOut)
次のように、一時的にsys.stdout
をStringIO
オブジェクトにリダイレクトするだけで、標準出力を簡単にキャプチャできます。
import StringIO
import sys
def foo(inStr):
print "hi"+inStr
def test_foo():
capturedOutput = StringIO.StringIO() # Create StringIO object
sys.stdout = capturedOutput # and redirect stdout.
foo('test') # Call unchanged function.
sys.stdout = sys.__stdout__ # Reset redirect.
print 'Captured', capturedOutput.getvalue() # Now works as before.
test_foo()
このプログラムの出力は次のとおりです。
Captured hitest
リダイレクトが出力を正常にキャプチャし、キャプチャを開始する前の状態に出力ストリームを復元できたことを示しています。
上のコードは、Python 2.7で、質問が示すとおりです。Python 3は少し異なります:
import io
import sys
def foo(inStr):
print ("hi"+inStr)
def test_foo():
capturedOutput = io.StringIO() # Create StringIO object
sys.stdout = capturedOutput # and redirect stdout.
foo('test') # Call function.
sys.stdout = sys.__stdout__ # Reset redirect.
print ('Captured', capturedOutput.getvalue()) # Now works as before.
test_foo()
このPython 3つの答えは unittest.mock
を使用します。また、再利用可能なヘルパーメソッドassert_stdout
を使用します、このヘルパーはテスト対象の機能に固有のものですが。
import io
import unittest
import unittest.mock
from .solution import fizzbuzz
class TestFizzBuzz(unittest.TestCase):
@unittest.mock.patch('sys.stdout', new_callable=io.StringIO)
def assert_stdout(self, n, expected_output, mock_stdout):
fizzbuzz(n)
self.assertEqual(mock_stdout.getvalue(), expected_output)
def test_only_numbers(self):
self.assert_stdout(2, '1\n2\n')
mock_stdout
argは、unittest.mock.patch
デコレータによってassert_stdout
メソッドに自動的に渡されることに注意してください。
汎用のTestStdout
クラス(おそらくmixin)は、原則として上記から派生できます。
Python≥3.4、 contextlib.redirect_stdout
を使用している場合もありますが、それ以上の利点はないようです。 unittest.mock.patch
。
偶然 pytest
を使用している場合、組み込みの出力キャプチャがあります。例(pytest
- styleテスト):
def eggs():
print('eggs')
def test_spam(capsys):
eggs()
captured = capsys.readouterr()
assert captured.out == 'eggs\n'
unittest
テストクラスでも使用できますが、たとえば自動使用フィクスチャを介してフィクスチャオブジェクトをテストクラスにパススルーする必要があります。
import unittest
import pytest
class TestSpam(unittest.TestCase):
@pytest.fixture(autouse=True)
def _pass_fixtures(self, capsys):
self.capsys = capsys
def test_eggs(self):
eggs()
captured = self.capsys.readouterr()
self.assertEqual('eggs\n', captured.out)
詳細については、 テスト関数からキャプチャされた出力へのアクセス をご覧ください。