Quelle est la façon propre de unittest FileField à django?
j'ai un modèle avec un champ de tir. Je veux unittest. django test framework a d'excellentes façons de gérer la base de données et les e-mails. Y a-t-il quelque chose de similaire pour FileFields?
Comment puis-je m'assurer que les unitts ne vont pas polluer la véritable application?
Merci d'avance
PS: ma question est presque une copie de Django test FileField en utilisant des fixtures de test mais il n'a pas de accepté de répondre. Je veux juste redemander si quelque chose de nouveau sur ce sujet.
4 réponses
il y a plusieurs façons de s'attaquer à cela, mais elles sont toutes laides puisque les tests unitaires sont censés être isolés, mais les fichiers sont tous sur les changements durables.
les tests de mon unité ne s'exécutent pas sur un système avec des données de production .il a donc été facile de réinitialiser le répertoire de téléchargement après chaque exécution avec quelque chose comme git reset --hard
. Cette approche est à certains égards la meilleure tout simplement parce qu'elle n'implique pas de changements de code et est garanti de fonctionner aussi longtemps que vous commencez avec un bon test données.
si vous n'avez pas réellement besoin de faire quoi que ce soit avec ce fichier après avoir testé la méthode de sauvegarde de votre modèle, je vous recommande d'utiliser l'excellente Bibliothèque simulée de python pour simuler complètement l'instance File
(i.e. quelque chose comme mock_file = Mock(spec=django.core.files.File); mock_file.read.return_value = "fake file contents"
) de sorte que vous pouvez éviter complètement les changements à votre logique de gestion de fichier. La bibliothèque simulée a plusieurs façons de globalement patch Django's classe de fichier dans un méthode d'essai qui est à peu près aussi facile que cela obtiendra.
si vous avez besoin d'un vrai fichier (c.-à-d. pour servir dans le cadre d'un test, traitement avec un script externe, etc.) vous pouvez utiliser quelque chose de similaire à L'exemple de Mirko et créer un File object après vous être assuré qu'il sera stocké quelque part approprié - voici trois façons de le faire:
- faites pointer votre test
settings.MEDIA_ROOT
vers un répertoire temporaire (voir le Python tempfile modulemkdtemp
fonction). Cela fonctionne très bien tant que vous avez quelque chose comme unSTATIC_ROOT
séparé que vous utilisez pour les fichiers médias qui font partie de votre code source.
"1519240920 Utiliser une" coutume gestionnaire de stockage
- définir le chemin du fichier manuellement sur chaque instance de fichier ou avoir un personnalisé upload_to fonction de pointer quelque part que votre test installation/démontage des purges de processus telles qu'un sous-répertoire test sous
MEDIA_ROOT
.
Edit: mock object library qui est nouveau dans la version de python 3.3. Pour les versions plus anciennes de python, cochez version de Michael Foord
Django fournit un excellent moyen de le faire - utiliser un simple fichier.
from django.core.files.uploadedfile import SimpleUploadedFile
my_model.file_field = SimpleUploadedFile('best_file_eva.txt', 'these are the file contents!')
c'est l'une des caractéristiques magiques de django-qui-n'apparaît-pas-dans-les-docs :). Toutefois, il est fait référence à ici .
j'ai l'habitude de tester filefields dans les modèles à l'aide de doctest
>>> from django.core.files import File
>>> s = SimpleModel()
>>> s.audio_file = File(open("media/testfiles/testaudio.wav"))
>>> s.save()
>>> ...
>>> s.delete()
si j'ai besoin de tester aussi des fichiers téléchargés avec des clients de test.
comme pour les fixtures, je copie simplement les fichiers dont j'ai besoin dans un dossier test, Après avoir modifié les chemins dans le fixture.
p.ex.
Dans un appareil contenant des modèles avec filefiels pointant vers un répertoire nommé "audio", vous remplacez "audio": "audio/audio.wav" avec "audio": "audio / test / audio.WAV. "
Maintenant, tout ce que vous avez à faire est de copier le dossier de test, avec les fichiers nécessaires, dans "audio" dans la configuration de test, puis de le supprimer dans tearDown.
Pas la façon la plus propre jamais je pense, mais c'est ce que je fais.
si vous voulez juste créer un objet qui nécessite FileField et ne veulent pas utiliser ce champ alors vous pouvez juste passer n'importe quel chemin relatif (existant ou non) comme ceci:
self.example_object = models.ExampleModel({'file': "foo.bar"})
self.example_object.save()
alors il est prêt à l'emploi.