python - simple - Django prueba FileField utilizando dispositivos de prueba
models filefield example (4)
Django proporciona una excelente manera de escribir pruebas en FileFields sin analizar el sistema de archivos real: use un archivo SimpleUploaded.
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 se muestran en los documentos :). Sin embargo se hace referencia here .
Estoy tratando de construir pruebas para algunos modelos que tienen un FileField. El modelo se ve así:
class SolutionFile(models.Model):
''''''
A file from a solution.
''''''
solution = models.ForeignKey(Solution)
file = models.FileField(upload_to=make_solution_file_path)
Me he encontrado con dos problemas:
Cuando se guardan datos en un dispositivo utilizando
./manage.py dumpdata
, el contenido del archivo no se guarda, solo el nombre del archivo se guarda en el dispositivo. Si bien creo que este es el comportamiento esperado, ya que el contenido del archivo no se guarda en la base de datos, me gustaría incluir esta información en el dispositivo para las pruebas.Tengo un caso de prueba para subir un archivo que se ve así:
def test_post_solution_file(self): import tempfile import os filename = tempfile.mkstemp()[1] f = open(filename, ''w'') f.write(''These are the file contents'') f.close() f = open(filename, ''r'') post_data = {''file'': f} response = self.client.post(self.solution.get_absolute_url()+''add_solution_file/'', post_data, follow=True) f.close() os.remove(filename) self.assertTemplateUsed(response, ''tests/solution_detail.html'') self.assertContains(response, os.path.basename(filename))
Si bien esta prueba funciona bien, deja el archivo cargado en el directorio de medios después de terminar. Por supuesto, la eliminación se podría tearDown()
en tearDown()
, pero me preguntaba si Django tenía otra forma de lidiar con esto.
Una solución en la que estaba pensando era utilizar una carpeta de medios diferente para las pruebas, que debe mantenerse sincronizada con los dispositivos de prueba. ¿Hay alguna forma de especificar otro directorio de medios en settings.py
cuando se están ejecutando pruebas? ¿Y puedo incluir algún tipo de enlace a dumpdata para que sincronice los archivos en las carpetas de medios?
Entonces, ¿hay una manera más específica de Pythonic o Django de tratar con pruebas unitarias que involucren archivos?
Esto es lo que hice para mi prueba. Después de cargar el archivo, debería terminar en la propiedad de foto del objeto modelo de mi organización:
import tempfile
filename = tempfile.mkstemp()[1]
f = open(filename, ''w'')
f.write(''These are the file contents'')
f.close()
f = open(filename, ''r'')
post_data = {''file'': f}
response = self.client.post("/org/%d/photo" % new_org_data["id"], post_data)
f.close()
self.assertEqual(response.status_code, 200)
## Check the file
## org is where the file should end up
org = models.Organization.objects.get(pk=new_org_data["id"])
self.assertEqual("These are the file contents", org.photo.file.read())
## Remove the file
import os
os.remove(org.photo.path)
He escrito pruebas unitarias para una aplicación de la galería completa antes, y lo que funcionó bien para mí fue usar los módulos de archivos temporales y de python para crear copias de los archivos de prueba en directorios temporales y luego eliminarlos todos.
El siguiente ejemplo no funciona / está completo, pero debería ponerlo en el camino correcto:
import os, shutil, tempfile
PATH_TEMP = tempfile.mkdtemp(dir=os.path.join(MY_PATH, ''temp''))
def make_objects():
filenames = os.listdir(TEST_FILES_DIR)
if not os.access(PATH_TEMP, os.F_OK):
os.makedirs(PATH_TEMP)
for filename in filenames:
name, extension = os.path.splitext(filename)
new = os.path.join(PATH_TEMP, filename)
shutil.copyfile(os.path.join(TEST_FILES_DIR, filename), new)
#Do something with the files/FileField here
def remove_objects():
shutil.rmtree(PATH_TEMP)
Ejecuto esos métodos en los métodos setUp () y tearDown () de mis pruebas unitarias y ¡funciona muy bien! Tienes una copia limpia de tus archivos para probar tu campo de archivos que son reutilizables y predecibles.
Puede anular la configuración de MEDIA_ROOT
para sus pruebas utilizando el decorador @override_settings()
como se documenta :
from django.test import override_settings
@override_settings(MEDIA_ROOT=''/tmp/django_test'')
def test_post_solution_file(self):
# your code here