Я вважаю за краще, щоб функції виводу явно приймали дескриптор файлу (або подібний до файлу об'єкт ), а не приймали ім'я файлу та самі відкривали файл. Таким чином, я можу передати StringIO
об'єкт функції виводу в моєму модульному тесті, потім .read()
вміст назад від цього StringIO
об'єкта (після .seek(0)
виклику) і порівняти з моїм очікуваним результатом.
Наприклад, ми перенесли б такий код
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")
кодувати так
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")
Цей підхід має додаткову перевагу, що робить вашу функцію виводу більш гнучкою, якщо, наприклад, ви вирішили, що не хочете писати у файл, а в інший буфер, оскільки він прийматиме всі файлоподібні об'єкти.
Зауважте, що використання StringIO
припускає, що вміст тестового результату може поміститися в основну пам’ять. Для дуже великих результатів ви можете використовувати підхід до тимчасових файлів (наприклад, tempfile.SpooledTemporaryFile ).
open
як описано в інших відповідях на цій сторінці, використовуючиunittest.mock
(див. відповідь Енріко М)