Как создать модель 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  
Вернуться на верх