Python:为控制台打印编写单元测试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33767627/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 13:56:41  来源:igfitidea点击:

Python: Write unittest for console print

pythonpython-2.7unit-testingconsolepython-unittest

提问by sudhishkr

Function fooprints to console. I want to test the console print. How can I achieve this in python?

函数foo打印到控制台。我想测试控制台打印。我怎样才能在 python 中实现这一点?

Need to test this function, has NO return statement :

需要测试这个函数,没有返回语句:

def foo(inStr):
   print "hi"+inStr

My test :

我的测试:

def test_foo():
    cmdProcess = subprocess.Popen(foo("test"), stdout=subprocess.PIPE)
    cmdOut = cmdProcess.communicate()[0]
    self.assertEquals("hitest", cmdOut)

采纳答案by paxdiablo

You can easily capture standard output by just temporarily redirecting sys.stdoutto a StringIOobject, as follows:

您可以通过临时重定向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()

The output of this program is:

这个程序的输出是:

Captured hitest

showing that the redirection successfully captured the output and that you were able to restore the output stream to what it was before you began the capture.

显示重定向成功捕获了输出,并且您能够将输出流恢复到开始捕获之前的状态。



Note that the code above in for Python 2.7, as the question indicates. Python 3 is slightly different:

请注意,如问题所示,上面针对 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()

回答by Acumenus

This Python 3 answer uses unittest.mock. It also uses a reusable helper method assert_stdout, although this helper is specific to the function being tested.

这个 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')

Note that the mock_stdoutarg is passed automatically by the unittest.mock.patchdecorator to the assert_stdoutmethod.

请注意,装饰器会mock_stdout自动将arg 传递unittest.mock.patchassert_stdout方法。

A general-purpose TestStdoutclass, possibly a mixin, can in principle be derived from the above.

一个通用TestStdout类,可能是一个 mixin,原则上可以从上面派生出来。

For those using Python ≥3.4, contextlib.redirect_stdoutalso exists, but it seems to serve no benefit over unittest.mock.patch.

对于那些使用 Python ≥3.4 的人,contextlib.redirect_stdout也存在,但它似乎对unittest.mock.patch.

回答by hoefling

If you happen to use pytest, it has builtin output capturing. Example (pytest-style tests):

如果您碰巧使用pytest,它具有内置的输出捕获。示例(pytest-style 测试):

def eggs():
    print('eggs')


def test_spam(capsys):
    eggs()
    captured = capsys.readouterr()
    assert captured.out == 'eggs\n'

You can also use it with unittesttest classes, although you need to passthrough the fixture object into the test class, for example via an autouse fixture:

您也可以将它与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)

Check out Accessing captured output from a test functionfor more info.

查看从测试函数访问捕获的输出以获取更多信息。