Django プロジェクトでは、アンマネージド モデル、つまりメタ オプションに manage = True が設定されていないモデルに遭遇することがあります。これらのモデルでは、特にテスト設定にマネージド モデルとアンマネージド モデルが混在している場合、または複数のデータベース (例: マネージド モデルとアンマネージド モデルを含む) が含まれる場合、テストが困難になる可能性があります。
このブログ投稿では、pytest-django を使用してアンマネージド モデルをテストするアプローチを検討し、これらのシナリオを効果的に管理するのに役立つ長所、短所、および回避策を強調します。
テスト中に非管理モデルを処理する簡単な方法の 1 つは、それらを一時的に管理対象としてマークすることです。その方法は次のとおりです:
# 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
注: このアプローチを機能させるには、pytest 設定 (または pytest.ini) に --no-migrations オプションを追加する必要があります
参照: スタック オーバーフロー
長所:
短所:
また、テスト設定中にアンマネージド モデルを手動で作成することもできます。このアプローチにより、移行が確実にテストされます:
@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)
長所:
短所:
Pytest-django は、データベース フィクスチャ django_db および django_db(transaction=True) を提供します。それぞれの違いは次のとおりです:
django_db: テスト ケースの終了時に変更をロールバックします。つまり、データベースへの実際のコミットは行われません。
django_db(transaction=True): 変更をコミットし、各テスト ケースの後にデータベース テーブルを切り捨てます。各テストの後に切り捨てられるのはマネージド モデルのみであるため、これが、トランザクション テスト中にアンマネージド モデルに特別な処理が必要になる理由です。
テストケースの例
@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
トランザクション テストではマネージド モデルのみが切り捨てられるため、テスト実行中にアンマネージド モデルを管理対象に変更できます。これにより、それらが切り捨てに確実に含まれるようになります:
# 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
on_commit フックが関係するシナリオでは、pytest-django(>= v.4.4) のフィクスチャ django_capture_on_commit_callbacks を使用して、on_commit コールバックを直接キャプチャして実行することで、トランザクション テストの使用を回避できます。
@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)
アンマネージド モデルを処理するための他のアプローチやヒントはありますか?以下のコメント欄で共有してください!
以上がPytest-Django でのアンマネージド モデルの処理の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。