Python:为控制台打印编写unittest

sud*_*hkr 28 python console unit-testing python-2.7 python-unittest

功能foo打印到控制台.我想测试控制台打印.我怎么能在python中实现这一点?

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

def foo(inStr):
   print "hi"+inStr
Run Code Online (Sandbox Code Playgroud)

我的测试:

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

pax*_*blo 41

您可以通过暂时重定向sys.stdoutStringIO对象来轻松捕获标准输出,如下所示:

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()
Run Code Online (Sandbox Code Playgroud)

该程序的输出是:

Captured hitest
Run Code Online (Sandbox Code Playgroud)

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


请注意,上面的代码适用于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()
Run Code Online (Sandbox Code Playgroud)

  • 在 Python `3.8.6` 中使用 `import io` 和 `io.StringIO()`。对于“SocketIO”,我得到“AttributeError:模块“io”没有属性“SocketIO””。 (5认同)

Acu*_*nus 24

这个Python 3示例建立在paxdiablo的基础之上.它使用unittest.mock.它使用可重用的辅助方法来进行断言.

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')
Run Code Online (Sandbox Code Playgroud)

通用assert_stdout类,可能是mixin,原则上可以从上面得出.


hoe*_*ing 5

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

def eggs():
    print('eggs')


def test_spam(capsys):
    eggs()
    captured = capsys.readouterr()
    assert captured.out == 'eggs\n'
Run Code Online (Sandbox Code Playgroud)

您还可以将其与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)
Run Code Online (Sandbox Code Playgroud)

检出从测试功能访问捕获的输出以获取更多信息。


sla*_*r98 5

您还可以使用如下所示的模拟包,这是来自https://realpython.com/lessons/mocking-print-unit-tests的示例 。

from mock import patch

def greet(name):
    print('Hello ', name)

@patch('builtins.print')
def test_greet(mock_print):
    # The actual test
    greet('John')
    mock_print.assert_called_with('Hello ', 'John')
    greet('Eric')
    mock_print.assert_called_with('Hello ', 'Eric')
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个,谢谢,效果很好。 (2认同)