Heim > Backend-Entwicklung > Python-Tutorial > Umgang mit nicht verwalteten Modellen in Pytest-Django

Umgang mit nicht verwalteten Modellen in Pytest-Django

Susan Sarandon
Freigeben: 2024-12-31 08:34:14
Original
297 Leute haben es durchsucht

Handling Unmanaged Models in Pytest-Django

Die Herausforderung beim Testen nicht verwalteter Modelle

In Django-Projekten stoßen wir gelegentlich auf nicht verwaltete Modelle – Modelle, die in ihren Metaoptionen nicht „managed = True“ haben. Diese Modelle können das Testen schwierig machen, insbesondere wenn Ihr Testaufbau eine Mischung aus verwalteten und nicht verwalteten Modellen oder mehrere Datenbanken umfasst (z. B. eine mit verwalteten Modellen und eine andere mit nicht verwalteten Modellen).

In diesem Blogbeitrag werden Ansätze zum Testen nicht verwalteter Modelle mit Pytest-Django untersucht und Vor- und Nachteile sowie Problemumgehungen hervorgehoben, die Ihnen bei der effektiven Verwaltung dieser Szenarien helfen.

Ansatz 1: Markieren Sie alle Modelle als verwaltet

Eine einfache Möglichkeit, mit nicht verwalteten Modellen während des Tests umzugehen, besteht darin, sie vorübergehend als verwaltet zu markieren. So können Sie es machen:

# Add this to conftest.py
@pytest.hookimpl(tryfirst=True)
def pytest_runtestloop():
    from django.apps import apps
    unmanaged_models = []
    for app in apps.get_app_configs():
        unmanaged_models += [m for m in app.get_models()
                             if not m._meta.managed]
    for m in unmanaged_models:
        m._meta.managed = True
Nach dem Login kopieren
Nach dem Login kopieren

Hinweis: Damit dieser Ansatz funktioniert, müssen Sie eine Option --no-migrations zu Ihren Pytest-Einstellungen (oder pytest.ini) hinzufügen

Referenz: Stapelüberlauf

Vorteile:

  • Einfach umzusetzen.

Nachteile:

  • Überspringt Migrationstests, die zu Problemen führen können, wenn mehrere Entwickler am selben Projekt arbeiten.

Ansatz 2: Nicht verwaltete Modelle manuell erstellen

Alternativ können Sie während des Testaufbaus manuell nicht verwaltete Modelle erstellen. Dieser Ansatz stellt sicher, dass Migrationen getestet werden:

@pytest.fixture(scope="session", autouse=True)
def django_db_setup(django_db_blocker, django_db_setup):
    with django_db_blocker.unblock():
        for _connection in connections.all():
            with _connection.schema_editor() as schema_editor:
                setup_unmanaged_models(_connection, schema_editor)
        yield

def setup_unmanaged_models(connection, schema_editor):
    from django.apps import apps

    unmanaged_models = [
        model for model in apps.get_models() if model._meta.managed is False
    ]
    for model in unmanaged_models:
        if model._meta.db_table in connection.introspection.table_names():
            schema_editor.delete_model(model)
        schema_editor.create_model(model)
Nach dem Login kopieren
Nach dem Login kopieren

Vorteile:

  • Testet Migrationen als Teil Ihrer Testfälle.

Nachteile:

  • Etwas komplexer.
  • transaction=True funktioniert mit diesem Ansatz nicht (wird im nächsten Abschnitt besprochen).

Transaktionale Tests verstehen

Pytest-django bietet eine Datenbankbefestigung: django_db und django_db(transaction=True). So unterscheiden sie sich:

django_db: Macht Änderungen am Ende eines Testfalls rückgängig, was bedeutet, dass kein tatsächlicher Commit in die Datenbank erfolgt.

django_db(transaction=True): Überträgt Änderungen und kürzt die Datenbanktabellen nach jedem Testfall. Da nach jedem Test nur verwaltete Modelle gekürzt werden, ist dies der Grund, warum nicht verwaltete Modelle bei Transaktionstests eine besondere Behandlung erfordern.

Beispieltestfall

@pytest.mark.django_db
def test_example():
    # Test case logic here
    pass

@pytest.mark.django_db(transaction=True)
def test_transactional_example():
    # Test case logic here
    pass
Nach dem Login kopieren

Damit Transaktionstests mit nicht verwalteten Modellen funktionieren

Da bei Transaktionstests nur verwaltete Modelle abgeschnitten werden, können wir nicht verwaltete Modelle so ändern, dass sie während des Testlaufs verwaltet werden. Dadurch wird sichergestellt, dass sie in die Trunkierung einbezogen werden:

# Add this to conftest.py
@pytest.hookimpl(tryfirst=True)
def pytest_runtestloop():
    from django.apps import apps
    unmanaged_models = []
    for app in apps.get_app_configs():
        unmanaged_models += [m for m in app.get_models()
                             if not m._meta.managed]
    for m in unmanaged_models:
        m._meta.managed = True
Nach dem Login kopieren
Nach dem Login kopieren

Vermeidung von „transaction=True“ mit on_commit-Hooks (falls möglich)

In Szenarien mit on_commit-Hooks können Sie die Verwendung von Transaktionstests vermeiden, indem Sie on_commit-Rückrufe direkt erfassen und ausführen, indem Sie Fixture django_capture_on_commit_callbacks von pytest-django(>= v.4.4) verwenden:

@pytest.fixture(scope="session", autouse=True)
def django_db_setup(django_db_blocker, django_db_setup):
    with django_db_blocker.unblock():
        for _connection in connections.all():
            with _connection.schema_editor() as schema_editor:
                setup_unmanaged_models(_connection, schema_editor)
        yield

def setup_unmanaged_models(connection, schema_editor):
    from django.apps import apps

    unmanaged_models = [
        model for model in apps.get_models() if model._meta.managed is False
    ]
    for model in unmanaged_models:
        if model._meta.db_table in connection.introspection.table_names():
            schema_editor.delete_model(model)
        schema_editor.create_model(model)
Nach dem Login kopieren
Nach dem Login kopieren

Referenzen

  • Pytest-Django-Dokumentation
  • Stack Overflow: Nicht verwaltete Modelle testen

Haben Sie weitere Ansätze oder Tipps für den Umgang mit nicht verwalteten Modellen? Teile sie unten in den Kommentaren!

Das obige ist der detaillierte Inhalt vonUmgang mit nicht verwalteten Modellen in Pytest-Django. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage