Подтвердить что ты не робот

Каков чистый способ unittest FileField в django?

У меня есть модель с FileField. Я хочу это сделать. В платформе django test есть отличные способы управления базами данных и электронной почтой. Есть ли что-то подобное для FileFields?

Как я могу убедиться, что unittests не загрязнят реальное приложение?

Заранее спасибо

PS: Мой вопрос - почти дубликат Django testFieldField с использованием тестовых устройств, но у него нет принятого ответа. Просто хочу спросить, есть ли что-то новое в этой теме.

4b9b3361

Ответ 1

Есть несколько способов справиться с этим, но все они безобразны, так как модульные тесты должны быть изолированными, а файлы - о долговременных изменениях.

Мои модульные тесты не выполняются в системе с производственными данными, поэтому было легко просто сбросить каталог загрузки после каждого запуска с чем-то вроде git reset --hard. Этот подход является в некотором смысле лучшим просто потому, что он не требует изменений кода и гарантированно будет работать, если вы начнете с хороших тестовых данных.

Если вам на самом деле ничего не нужно делать с этим файлом после тестирования метода сохранения модели, я бы порекомендовал использовать превосходную Mock-библиотеку pya, чтобы полностью подделать экземпляр File (то есть что-то вроде mock_file = Mock(spec=django.core.files.File); mock_file.read.return_value = "fake file contents"), чтобы вы могли полностью избежать изменений в логике обработки файлов. В библиотеке Mock есть несколько способов глобально исправить Django класс файлов в тестовом методе, который настолько прост, насколько это возможно.

Если вам нужен реальный файл (т.е. для использования в качестве части теста, обработки с помощью внешнего скрипта и т.д.), Вы можете использовать что-то похожее на пример Мирко и создать объект File, убедившись в этом. будет храниться в подходящем месте - вот три способа сделать это:

  • Пусть ваш тест settings.MEDIA_ROOT указывает на временный каталог (см. функцию Python временного файла модуля mkdtemp). Это прекрасно работает, если у вас есть что-то вроде отдельного STATIC_ROOT, который вы используете для медиа файлов, которые являются частью вашего исходного кода.
  • Используйте собственный диспетчер хранилища
  • Задайте путь к файлу вручную для каждого экземпляра файла или используйте пользовательскую функцию upload_to, чтобы указать куда-то, что очищает процесс установки/удаления теста, например подкаталог test в MEDIA_ROOT.

Редактировать: библиотека фиктивных объектов появилась в Python версии 3.3. Для более старых версий Python проверьте версию Michael Foord

Ответ 2

Django предоставляет отличный способ сделать это - использовать SimpleUploadedFile.

from django.core.files.uploadedfile import SimpleUploadedFile

my_model.file_field = SimpleUploadedFile(
    "best_file_eva.txt",
    b"these are the file contents!"   # note the b in front of the string [bytes]
)

Это одна из магических функций Django, которые не появляются в документах :). Однако он упоминается здесь как here.

Для Python 2

Если вы застряли на Python 2, пропустите префикс b в содержимом:

my_model.file_field = SimpleUploadedFile(
    "best_file_eva.txt",
    "these are the file contents!" # no b
)

Ответ 3

Я обычно тестирую файловые поля в моделях с помощью doctest

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

Если мне нужно также проверить загрузки файлов с помощью тестовых клиентов.

Что касается приспособлений, я просто копирую файлы, которые мне нужны в тестовой папке, после изменения путей в приборе.

например.

В устройстве, содержащем модели с файловыми файлами, указывающими на каталог с именем "audio", вы заменяете "audio": "audio/audio.wav" на "audio": "audio/test/audio.wav".
Теперь все, что вам нужно сделать, это скопировать тестовую папку с необходимыми файлами в "audio" в тестовом комплектеUp и затем удалить ее в tearDown.

Не самый чистый путь, когда-либо я думаю, но это то, что я делаю.

Ответ 4

Если вы просто хотите создать объект, для которого требуется FileField, и не хотите использовать это поле, тогда вы можете просто передать любой (существующий или нет) относительный путь, например так:

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

Тогда он готов к использованию.