Testeando archivos con Python/Django
Uno de los momentos más importantes al escribir una aplicación en Python es testear. Esta buena práctica puede salvarte cuando, por ejemplo, un compañero (que puedes ser tú), desorganiza el código antes de una entrega. También te ayudará con esos bugs complicados que se escabullen. En este post una muestra de cómo escribir una prueba de testeo que implique archivos.
Como no encontré información pertinente sobre cómo escribir pruebas que implicaron archivos, decidí escribir este post.
En mi caso, necesitaría probar imágenes, pero lo descrito aquí está limitado para cualquier tipo de archivo.
Recuerda que una buena idea es testear todo lo que programes, por tedioso que sea.
Primero lo primero, no llenar el servidor de basura
La poca información que encontré sobre el tema de te stear archivos implicaba crear un archivo por cada vez que se corría el test, es decir, dejar archivos perdidos en alguna de las carpetas del proyecto por el resto de la eternidad (De este tema hablaré luego ).
El comportamiento mencionado no me agrada, porque si mi proyecto implica muchas pruebas con archivos se crearía dema siada «basura» en el servidor, la cual, luego, necesitaría eliminar manualmente.
Por lo anterior, busqué otra solución y la descubrí en la librería de Python tempfile.
Al usar esta librería, junto con override_settings de django.test , se crearán archivos temporales en una carpeta que el sistema se encargará de borrar, eventualmente.
Veamos el proceso paso por paso.
Paso 1. Escribir un modelo básico:
[code lang="python"] de los modelos de importación django.db clase Imagen(modelos.Modelo): imagen = modelos.ImageField() [/código]
Paso 2. Escribir un test sencillo:
[código lang="python"] de PIL importar imagen importar archivo temporal de django.test importar TestCase de .models importar imagen de django.test importar override_settings def get_temporary_image(temp_file): tamaño = (200, 200) color = (255, 0, 0, 0) imagen = Imagen.nueva("RGBA", tamaño, color) image.save(temp_file, 'jpeg') return archivo_temp clase PictureDummyTest(TestCase): @override_settings(MEDIA_ROOT=tempfile.gettempdir()) def test_dummy_test(self): temp_file = tempfile.NamedTemporaryFile() test_image = get_temporary_image(temp_file) #test_image.seek(0) picture = Picture.objects.create(picture=test_image.name ) print "¡Funcionó!, ", imagen.imagen self.assertEqual(len(Imagen.objetos.todos()), 1) [/código]
Paso 3. Notar el decorador y sobrescribir la ruta del archivo
Lo primero que hay que notar es el decorador @override_settings . Este permite sobrescribir las variables de configuración que serán usadas mientras el test se corre.
Para este caso, la variable MEDIA_ROOT es la ruta del sistema donde Django guarda todos los archivos subidos por el usuario, pero si no está sobrescrita todas las imágenes creadas las pruebas se guardaran allí, llenando de basura nuestro servidor.
Un modo de solucionar lo anterior es sobrescribir esta ruta con tempfile.gettempdir().
Esta función de la librería tempfile devolverá el nombre del directorio usado para archivos temporales:
(retornará /tmp, /var/tmp, /usr/tmp o similar, dependiendo del sistema operativo utilizado).
Al ejecutar este paso, todas las imágenes creadas durante las pruebas estarán guardadas en el directorio temporal y eventualmente serán borradas por el sistema operativo. De esta manera no quedará basura en mi servidor cuando las pruebas terminen de correr.
Paso 4 . Crear un archivo temporal
La función tempfile.NamedTemporaryFile() de la librería tempfile crea un archivo temporal con un nombre visible en el sistema de archivos (la ruta visible de dónde está localizado este archivo).
Este archivo temporal se usa luego por la función get_temporary_image para crear un pequeño cuadrado rojo y guardarlo.
Posteriormente, le décimos a Django dónde encontrar el archivo con el siguiente código:
[código]imagen = Imagen.objetos.create(imagen=imagen_de_prueba.nombre)[/código]
Con lo anterior le digo a Django que cree una instancia del modelo Picture con test_image como su campo Picture.
Nótese que estoy usando test_image.name para decirle a Django la ruta donde está test_image.
Luego de esto, Django tomará la imagen y guardará una copia relacionada con la instancia del modelo Picture que creó en MEDIA_ROOT (que sobrescribimos).
Al correr el test, la respuesta del print será:
[código]¡Funcionó!, /tmp/tmpIp8YS0[/código]
Como puede ver, la imagen se guardó en /tmp/ por lo que el sistema operativo la borrará.
Consejo final
Para probar imágenes como archivos adjuntos en una solicitud HTTP, utilice la imagen creada en los datos sin utilizar el nombre de la imagen (.name) , ya que está adjuntando la imagen, no su nombre.
Utilice, además, test_image.seek (0) para buscar el primer cuadro, como si la imagen acabara de abrirse.
En este enlace encontrará más información sobre el proceso, utilizando El módulo de imágenes PIL.
[code lang="python"] test_image.seek(0) respuesta = self.client.put( self.reverse('upload_user_picture'), {'profile_picture': test_image}) [/code]
Espero que este pequeño tutorial le sea de utilidad.