Я предпочитаю, чтобы выходные функции явно принимали файл handle (или файлоподобный object ), а не принимали файл name и открывали файлсамих себя.Таким образом, я могу передать объект StringIO
в функцию вывода в моем модульном тесте, затем .read()
содержимое обратно из этого объекта StringIO
(после вызова .seek(0)
) и сравнить смой ожидаемый результат.
Например, мы должны преобразовать код, подобный этому
##File:lamb.py
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])
##File test_lamb.py
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:
# NOTE: To retain the tempfile if the test fails, remove
# the try-finally clauses
os.remove(outfile_path)
self.assertEqual(result, "Mary had a little lamb.\n")
, в код, подобный этому
##File:lamb.py
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)
##File test_lamb.py
import unittest
from io import StringIO
import lamb
class LambTests(unittest.TestCase):
def test_lamb_output(self):
outfile = StringIO()
# NOTE: Alternatively, for Python 2.6+, you can use
# tempfile.SpooledTemporaryFile, e.g.,
#outfile = tempfile.SpooledTemporaryFile(10 ** 9)
lamb.write_lamb(outfile)
outfile.seek(0)
content = outfile.read()
self.assertEqual(content, "Mary had a little lamb.\n")
Этот подход имеет дополнительное преимущество, заключающееся вФункция вывода более гибкая, если, например, вы решите, что хотите записывать не в файл, а в какой-то другой буфер, поскольку он будет принимать все файловые объекты.
Обратите внимание, что использование StringIO
предполагаетсодержимое тестового вывода может помещаться в основную память.Для очень больших выходных данных вы можете использовать подход временного файла (например, tempfile.SpooledTeilitaryFile ).