¿Cuál es la forma limpia de unittest FileField en django?


Tengo un modelo con un campo de archivos. Quiero probarlo. django test framework tiene excelentes maneras de administrar bases de datos y correos electrónicos. ¿Hay algo similar para FileFields?

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

Gracias de antemano

PD: Mi pregunta es casi un duplicado de Django test FileField usando accesorios de prueba pero no tiene una respuesta aceptada. Sólo quiero volver a preguntar si algo nuevo en este tema.

Author: Community, 2010-11-26

4 answers

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

Mis pruebas unitarias no se ejecutan en un sistema con datos de producción, por lo que ha sido fácil simplemente restablecer 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 y cuando comience con buenos datos de prueba.

Si no lo haces realmente necesita hacer cualquier cosa con ese archivo después de probar el método de guardado de su modelo, le recomendaría usar la excelente biblioteca de simulación de python para falsificar completamente la instancia File (es decir, algo como mock_file = Mock(spec=django.core.files.File); mock_file.read.return_value = "fake file contents") para que pueda evitar completamente los cambios en su lógica de manejo de archivos. La biblioteca Simulada tiene un par de maneras de globalmente patch La clase de archivo de Django 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, procesar con un script externo, etc. puede usar algo similar al ejemplo de Mirko y crear un File object después de asegurarse de que se almacenará en un lugar apropiado, aquí hay tres formas de hacerlo:

  • Haga que su prueba settings.MEDIA_ROOTapunte a un directorio temporal (vea la función mkdtemp del módulo Python tempfile ). Esto funciona bien siempre y cuando tenga algo como un STATIC_ROOT separado que use para los archivos multimedia que forman parte de tu código fuente.
  • Utilice un gestor de almacenamiento personalizado
  • Establezca la ruta del archivo manualmente en cada instancia de archivo o tenga una función personalizada upload_to para apuntar a algún lugar que su proceso de configuración/desmontaje de prueba purgue, como un subdirectorio de prueba bajo MEDIA_ROOT.

Editar: la biblioteca de objetos simulados es nueva en python versión 3.3. Para versiones anteriores de python, compruebe La versión de Michael Foord

 32
Author: Chris Adams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-16 21:51:33

Django proporciona una gran manera de hacer esto - 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 mágicas de django-que-no-aparecen-en-los-documentos:). Sin embargo se hace referencia a aquí.

 68
Author: waterproof,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-11 01:06:30

Normalmente pruebo campos de archivos 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 lo necesito, también pruebo las subidas de archivos con clientes de prueba.

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

Por ejemplo

En un accesorio que contiene modelos con filefiels apuntando a un directorio llamado "audio", se reemplaza "audio": "audio/audio.wav" con "audio": "audio/test/audio.wav".
Ahora todo lo que tienes que hacer es copiar la carpeta de prueba, con los archivos necesarios, en "audio" en la configuración de prueba y luego eliminarlo en Desmontaje.

No es la forma más limpia que he pensado, pero eso es lo que hago.

 10
Author: Mirko Rossini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-26 17:08:04

Si solo desea crear un objeto que requiera FileField y no desea usar este campo entonces puede pasar cualquier ruta relativa (existente o no) como esta:

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

Entonces está listo para su uso.

 0
Author: Ctrl-C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-20 12:08:33