Wolę, aby funkcje wyjściowe wyraźnie akceptowały uchwyt pliku (lub obiekt podobny do pliku ), zamiast akceptować nazwę pliku i same otwierać plik. W ten sposób mogę przekazać StringIO
obiekt do funkcji wyjściowej w moim teście jednostkowym, a następnie .read()
zawartość z powrotem z tego StringIO
obiektu (po .seek(0)
wywołaniu) i porównać z oczekiwanymi wynikami.
Na przykład moglibyśmy zmienić kod w ten sposób
import sys
def write_lamb(outfile_path):
with open(outfile_path, 'w') as outfile:
outfile.write("Mary had a little lamb.\n")
if __name__ == '__main__':
write_lamb(sys.argv[1])
import unittest
import tempfile
import lamb
class LambTests(unittest.TestCase):
def test_lamb_output(self):
outfile_path = tempfile.mkstemp()[1]
try:
lamb.write_lamb(outfile_path)
contents = open(tempfile_path).read()
finally:
os.remove(outfile_path)
self.assertEqual(result, "Mary had a little lamb.\n")
kodować w ten sposób
import sys
def write_lamb(outfile):
outfile.write("Mary had a little lamb.\n")
if __name__ == '__main__':
with open(sys.argv[1], 'w') as outfile:
write_lamb(outfile)
import unittest
from io import StringIO
import lamb
class LambTests(unittest.TestCase):
def test_lamb_output(self):
outfile = StringIO()
lamb.write_lamb(outfile)
outfile.seek(0)
content = outfile.read()
self.assertEqual(content, "Mary had a little lamb.\n")
Takie podejście ma tę dodatkową zaletę, że sprawia, że funkcja wyjściowa jest bardziej elastyczna, jeśli na przykład zdecydujesz, że nie chcesz zapisywać do pliku, ale do innego bufora, ponieważ akceptuje on wszystkie obiekty podobne do plików.
Zauważ, że użycie StringIO
zakłada, że zawartość wyjścia testowego zmieści się w pamięci głównej. W przypadku bardzo dużych danych wyjściowych można użyć metody pliku tymczasowego (np. Tempfile.SpooledTemporaryFile ).
open
zgodnie z opisem w innych odpowiedziach na tej stronie, używającunittest.mock
(patrz odpowiedź od Enrico M)