Prefiero que las funciones de salida acepten explícitamente un identificador de archivo (u objeto similar a un archivo), en lugar de aceptar un nombre de archivo y abrir el archivo ellos mismos. De esta manera, puedo pasar un StringIO
objeto a la función de salida en mi prueba unitaria, luego .read()
el contenido de ese StringIO
objeto (después de una .seek(0)
llamada) y compararlo con mi salida esperada.
Por ejemplo, haríamos una transición de código como este
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")
codificar como este
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")
Este enfoque tiene el beneficio adicional de hacer que su función de salida sea más flexible si, por ejemplo, decide que no desea escribir en un archivo, sino en algún otro búfer, ya que aceptará todos los objetos similares a archivos.
Tenga en cuenta que el uso StringIO
supone que el contenido de la salida de prueba puede caber en la memoria principal. Para una salida muy grande, puede utilizar un enfoque de archivo temporal (por ejemplo, tempfile.SpooledTemporaryFile ).