Python:为控制台打印编写unittest

问题描述 投票:20回答:2

功能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)
python python-2.7 unit-testing console python-unittest
2个回答
37
投票

您可以通过暂时将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()

20
投票

这个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更有益。


1
投票

如果您碰巧使用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了解更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.