2010-11-26 35 views
33

Tengo un modelo con un FileField. Quiero probarlo. El marco de prueba django tiene excelentes maneras de administrar bases de datos y correos electrónicos. ¿Hay algo similar para FileFields?¿Cuál es la forma limpia de probar FileField en django?

¿Cómo puedo asegurarme de que los unittest no vayan a contaminar la aplicación real?

Gracias de antemano

PS: Mi pregunta es casi un duplicado de Django test FileField using test fixtures pero no tiene una respuesta aceptada. Solo quiero volver a preguntar si hay algo nuevo sobre este tema.

+1

Posible duplicado de [Django test FileField utilizando accesorios de prueba] (http://stackoverflow.com/questions/2266503/django-test-filefield-using-test-fixtures) – waterproof

Respuesta

31

Hay varias formas de abordar esto, pero todas son feas, ya que se supone que las pruebas unitarias deben estar aisladas, pero los archivos son sobre cambios duraderos.

Las pruebas de mi unidad no se ejecutan en un sistema con datos de producción, por lo que es fácil simplemente reiniciar el directorio de carga después de cada ejecución con algo como git reset --hard. Este enfoque es, de alguna manera, el mejor, simplemente porque no implica cambios de código y está garantizado que funcionará siempre que comience con buenos datos de prueba.

Si usted realmente no necesita hacer nada con ese archivo después de probar método save de su modelo, me gustaría recomendar el uso de Michael Foord excelente Mock library de falsificar la File instancia (es decir, algo así como mock_file = Mock(spec=django.core.files.File); mock_file.read.return_value = "fake file contents") para que pueda evitar por completo por completo cambios a su lógica de manejo de archivos. La biblioteca Mock tiene un par de maneras de globally patch Django's File class dentro de un método de prueba que es casi tan fácil como esto.

Si necesita tener un archivo real (es decir, para servir como parte de una prueba, procesarlo con un script externo, etc.) puede usar algo similar al ejemplo de Mirko y crear un File object después de asegurarse de que será almacenados en algún lugar apropiado - aquí hay tres maneras de hacerlo:

  • Tiene su punto de prueba settings.MEDIA_ROOT a un directorio temporal (véase la función del módulo de Python tempfilemkdtemp). Esto funciona bien siempre que tenga algo así como un STATIC_ROOT separado que use para los archivos multimedia que son parte de su código fuente.
  • Utilice una costumbre storage manager
  • Establecer la ruta del archivo de forma manual en cada instancia del archivo o tienen una función personalizada upload_to señalar alguna parte que sus purgas proceso de instalación de prueba/desmontaje como un subdirectorio de prueba bajo MEDIA_ROOT.
+0

Gracias por esta gran respuesta. Finalmente escogí apuntar a una prueba de unidad MEDIA_ROOT cambiando el valor de esta variable en la configuración de mi caso de prueba – luc

+1

simulacro ahora es parte de la biblioteca estándar de Python, disponible como unittest.mock en Python 3.3 en adelante - Recolectado de REAME. rst – chachan

+0

@chachan puede sugerir una edición? Esa respuesta definitivamente se debe a una actualización –

10

que normalmente probar filefields en modelos usando doctest

>>> from django.core.files import File 
>>> s = SimpleModel() 
>>> s.audio_file = File(open("media/testfiles/testaudio.wav")) 
>>> s.save() 
>>> ... 
>>> s.delete() 

Si necesito yo también la carga de archivos de prueba con clientes de prueba.

En cuanto a los accesorios, simplemente copio los archivos que necesito en una carpeta de prueba, después de modificar las rutas en el dispositivo.

p. Ej.

En un aparato que contiene modelos con archivos que apuntan a un directorio llamado "audio", reemplaza "audio": "audio/audio.wav" con "audio": "audio/prueba/audio.wav".
Ahora todo lo que tiene que hacer es copiar la carpeta de prueba, con los archivos necesarios, en "audio" en la configuración de prueba y luego eliminarla en tearDown.

No es la manera más limpia que haya pensado, pero eso es lo que hago.

+0

¿Cómo puedo hacer esto con un ImageField? ? –

+0

¿Debo cerrar manualmente el archivo para liberar los recursos que usa? – Pieter

0

Si lo que desea es crear un objeto que requiere FileField y no quieren usar este campo a continuación, puedes pasar cualquier ruta relativa (existente o no) de esta manera:

self.example_object = models.ExampleModel({'file': "foo.bar"}) 
self.example_object.save() 

Luego está listo para usar.

58

Django proporciona una excelente manera de hacerlo: use un SimpleUploadedFile.

from django.core.files.uploadedfile import SimpleUploadedFile 

my_model.file_field = SimpleUploadedFile('best_file_eva.txt', 'these are the file contents!') 

Es una de las características-que-no-show-up-en-el-docs mágicos de Django :). Sin embargo, se refiere a here.

+0

No sabía esto. Gracias por tu comentario. Lo investigaré – luc

+5

El contenido * debe * ser str() en Python 2.xy bytes() en Python 3.x. No puedes poner texto/unicode allí. – kaleissin

+1

Sé que estoy preguntando esto 4 años después, pero ... ¿Hay alguna forma de falsificar el tamaño del archivo? – pta2002

Cuestiones relacionadas