Как создать модель Django только для тестирования в целом (и с помощью pytest-django в частности)
Общий вопрос: У меня есть абстрактная модель, которую я хочу протестировать с реальным экземпляром модели, однако я не хочу полностью перестраивать свой проект/формат тестов. См. эти два ответа для справки: Первый ответ Второй ответ
Я хочу A) Определять модели внутри каждой папки тестовых приложений и не определять их внутри реальных приложений B) Не иметь дополнительных/отдельных конфигураций apps.py и settings.py для каждой тестовой папки. Я знаю, что это возможно, потому что проект django имеет очень похожую структуру тестов, подобную этой, но они используют скрипт запуска тестов, который я не могу полностью расшифровать.
Папка test/ отражает структуру приложений, которые у меня есть (а это blog/, projects/, richeditable/).
backend
├── projects
├── blog
├── richeditable
├── tests
│ ├── __init__.py
│ ├── conftest.py
│ ├── blog
│ │ ├── ...
│ ├── projects
│ │ ├── ...
│ └── richeditable
│ │ ├── __init__.py
│ │ ├── test_model.py
│ │ ├── models.py <-------------- This defines a model that inherits from richeditable.models
# richeditable/models.py
class Draftable(models.Model):
blah = models.IntegerField()
class Meta:
abstract = True
# tests/richeditable/models.py
class DummyDraftable(Draftable):
additional_field = models.BooleanField()
# class Meta:
# app_label = "some_app"
# ^--- Django does not seem to like having this blank and I don't know what to put to make this work
# tests/richeditable/test_model.py
import pytest
@pytest.fixture
def add_app(settings):
settings.INSTALLED_APPS += ['backend.tests.richeditable']
# presumably the above fixture would affect the apps/models
# settings before the database is created, but that does not seems to be the case
def test_please_work(add_app, db):
assert DummyDraftable.objects.create(blah=1, additional_field=True) is not None
Из того, что я видел о сценарии проекта django, я могу предположить, что они загружают каждую папку для тестирования как модуль и добавляют его в INSTALLED_APPS
во время выполнения перед тестовыми примерами. Однако вы не можете просто изменить INSTALLED_APPS
, потому что добавляются модели, и миграции должны быть сделаны в тестовую базу данных заранее, а также, похоже, есть необходимость определить AppConfig
(потому что Django теряет рассудок, если вы этого не делаете). Я пытался включить поле app_label
Meta для моделей, но это не сработало, или я мог сделать что-то не так. Но дело в том, что я не вижу скрипта, создающего AppConfig
и им почему-то не нужно объявлять Meta
в своем models.py
Специфические вещи для pytest:
С pytest-django все становится еще сложнее, потому что он не использует интерфейс Django TestRunner
. Вот как бы вы это сделали , если бы это было так (обратите внимание на порядок операций). Я уже пробовал модифицировать приспособление settings
pytest перед инстанцированием db со связанными приспособлениями, но это не приводит к загрузке модуля, что бы я ни делал. Из просмотра исходного кода кажется, что настройки фиксируются на месте, основываясь на том, что указано в settings.py, и модификация settings
фикстур не имеет никакого значения для загрузки приложения.
В итоге я решил свою проблему самостоятельно. Как упомянул @hoefling, лучший способ - создать отдельный файл настроек, расширяющий ваш обычный файл настроек, и указать его в качестве файла настроек pytest.
// pytest.ini
[pytest]
addopts = --ds=config.settings.test
Важно отметить, что, как я выяснил, вы не можете использовать тестовые модули с тем же именем, что и уже существующие приложения. Так что структура, которую я имел с backend/tests/richeditable, недопустима, что бы вы ни делали. Поэтому я добавил к каждой папке test_
и все работает нормально. Это также решает проблему необходимости включения app_label
в ваши модели.
# testsettings.py
from .settings import * # noqa
INSTALLED_APPS += [
'backend.tests.test_projects',
'backend.tests.test_blog',
'backend.tests.test_richeditable',
]
backend
├── projects
├── blog
├── richeditable
├── tests
│ ├── __init__.py
│ ├── conftest.py
│ ├── test_blog
│ │ ├── ...
│ ├── test_projects
│ │ ├── ...
│ └── test_richeditable
│ │ ├── __init__.py
│ │ ├── test_model.py
│ │ ├── models.py