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.
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
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:
Nachteile:
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)
Vorteile:
Nachteile:
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
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
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)
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!