La fonction foo
s'imprime sur la console. Je veux tester l'impression de la console. Comment puis-je y parvenir en python?
Besoin de tester cette fonction, n'a AUCUNE déclaration de retour:
def foo(inStr):
print "hi"+inStr
Mon test :
def test_foo():
cmdProcess = subprocess.Popen(foo("test"), stdout=subprocess.PIPE)
cmdOut = cmdProcess.communicate()[0]
self.assertEquals("hitest", cmdOut)
Vous pouvez facilement capturer la sortie standard en redirigeant simplement temporairement sys.stdout
à un objet StringIO
, comme suit:
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()
Le résultat de ce programme est:
Captured hitest
montrant que la redirection a correctement capturé la sortie et que vous avez pu restaurer le flux de sortie à ce qu'il était avant de commencer la capture.
Notez que le code ci-dessus pour Python 2.7, comme l'indique la question. Python 3 est légèrement différent:
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()
Cette réponse Python 3 utilise unittest.mock
. Il utilise également une méthode d'assistance réutilisable assert_stdout
, bien que cet assistant soit spécifique à la fonction testée.
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')
Notez que le mock_stdout
arg est passé automatiquement par le unittest.mock.patch
décorateur au assert_stdout
méthode.
Une classe TestStdout
à usage général, éventuellement un mixage, peut en principe être dérivée de ce qui précède.
Pour ceux qui utilisent Python ≥3.4, contextlib.redirect_stdout
existe également, mais il semble n'avoir aucun avantage sur unittest.mock.patch
.
S'il vous arrive d'utiliser pytest
, il a une capture de sortie intégrée. Exemple (tests de style pytest
):
def eggs():
print('eggs')
def test_spam(capsys):
eggs()
captured = capsys.readouterr()
assert captured.out == 'eggs\n'
Vous pouvez également l'utiliser avec les classes de test unittest
, bien que vous deviez passer l'objet fixture dans la classe de test, par exemple via un fixture autouse:
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)
Consultez Accès à la sortie capturée à partir d'une fonction de test pour plus d'informations.