功能foo
打印到控制台。我想测试控制台打印。我怎么能在python中实现这一点?
需要测试这个函数,有没有返回语句:
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
更有益。
如果您碰巧使用qazxsw poi,它内置输出捕获。示例(qazxsw poi-style tests):
pytest
您也可以将它与pytest
测试类一起使用,尽管您需要将fixture对象传递到测试类中,例如通过autouse fixture:
def eggs():
print('eggs')
def test_spam(capsys):
eggs()
captured = capsys.readouterr()
assert captured.out == 'eggs\n'
查看unittest
了解更多信息。