Django 1.7で単体テストを実行するときに移行を無効にする


110

Django 1.7では、データベースの移行が導入されました。

Django 1.7でユニットテストを実行すると、移行が強制的に行われ、時間がかかります。だから私はdjangoの移行をスキップして、最終的な状態でデータベースを作成したいと思います。

コードのその部分はテストされないので、移行を無視することは悪い習慣になることを知っています。しかし、そうではありません。CIテストサーバー(ジェンキンス)で完全な移行を実行しています。速度が重要なローカルテストでは、移行をスキップしたいだけです。


いくつかのコンテキスト:

Django 1.6まで、Southを使用するときは、SOUTH_TESTS_MIGRATE設定を使用していました

デフォルトでは、Southのsyncdbコマンドは、非インタラクティブモードで実行されている場合、移行を適用します。これには、テストの実行時も含まれます。テストを実行するたびにすべての移行が実行されます。

テストランナーで移行の代わりにsyncdbを使用する場合-たとえば、移行の適用に時間がかかりすぎる場合は、settings.pyでSOUTH_TESTS_MIGRATE = Falseを設定するだけです。

ただし、syncdbはもう存在していません。現在は移行しています。

Django 1.8以降--keepdbパラメータを使用します。

--keepdbオプションを使用すると、テスト実行間でテストデータベースを保持できます。これには、作成アクションと破棄アクションの両方をスキップするという利点があり、特に大規模なテストスイートでのテストの実行時間を大幅に短縮します。テストデータベースが存在しない場合、最初の実行時に作成され、その後の実行ごとに保存されます。適用されていない移行は、テストスイートを実行する前にテストデータベースにも適用されます。

したがって、この質問はDjango 1.7に限定されています。


私は、UTの間、最初からDBが存在しないため、それらをテストする方法で移行を実際に実行していないと主張します。移行のテストは、実際には、既存のDBを移行する場合にのみ行われます。この1.7の移行ビジネスは、私がDjangoで使ったサドルの下での最初の本当の難題ですが、それは本当に大きな刺激です。South氏は少なくとも、移行に適したテストシナリオを得ました。
ボートコーダー、2014年

django-test-without-migrationsパッケージには、あなたが受け入れ答えを変更したい場合があります、私にとって本当に便利となっているstackoverflow.com/a/28993456/200224
アンディ・

可能であれば、新しい依存関係を追加しないようにします。
David Arcos

回答:


79

Bernie SumptionがDjango開発者のメーリングリストに投稿したこの回避策をご覧ください

makemigrationsがまだ実行されていない場合、「migrate」コマンドはアプリを未移行として扱い、1.6でsyncdbが行ったようにモデルから直接テーブルを作成します。「settings_test.py」と呼ばれる単体テスト専用の新しい設定モジュールを定義しました。これは、メイン設定モジュールから*をインポートし、次の行を追加します。

MIGRATION_MODULES = {"myapp": "myapp.migrations_not_used_in_tests"}

次に、次のようなテストを実行します。

DJANGO_SETTINGS_MODULE = "myapp.settings_test" python manage.py test

このばか者は、アプリが移行されていないという考えに移行するため、テストデータベースが作成されるたびに、models.pyの現在の構造が反映されます。

Django 1.9では、この状況が多少改善され、値をNone次のように設定できます。

MIGRATION_MODULES = {"myapp":なし}


9
myapp.migrations_not_used_in_testsモジュールが存在してはならないことに注意してください。
bmihelac 14

4
モジュールが存在しないことについてのコメント@bmihelacに加えて、モジュール文字列にはサブ文字列「migrations」が含まれている必要があります。理由については、github.com
nealtodd '19

7
settings_test.pyでMIGRATION_MODULESを
nealtodd

1
TY。これにより、ユニットテストを13秒から4秒に減らすことができました。また、テストにsqliteを使用すると、速度の向上が見られます。私にとって、テストにpostgresを使用すると5.5秒かかりますが、sqliteには4秒かかります。
Gattster 2014年

21
@nealtoddの要旨のコメントから、いくつかの落とし穴を回避し、非常にシンプルなソリューションへのリンクを次に示し
NotSqrt

72

これが私の設定ファイルの終わりです:

class DisableMigrations(object):

    def __contains__(self, item):
        return True

    def __getitem__(self, item):
        return None


TESTS_IN_PROGRESS = False
if 'test' in sys.argv[1:] or 'jenkins' in sys.argv[1:]:
    logging.disable(logging.CRITICAL)
    PASSWORD_HASHERS = (
        'django.contrib.auth.hashers.MD5PasswordHasher',
    )
    DEBUG = False
    TEMPLATE_DEBUG = False
    TESTS_IN_PROGRESS = True
    MIGRATION_MODULES = DisableMigrations()

このスニペットに基づいて

テストの実行中にのみ移行を無効にしました


1
いいね!__setitem__(self, *_)独自の移行を設定するアプリに問題があったため、メソッドも追加します settings.MIGRATION_MODULES['chroniker'] = 'db_migrations'
Zhe Li

1
本当にありがとうございました。実際に機能するのはそれだけです。
Fluffels

Django 1.9では、テストを並列モードで実行している場合、これは機能しません。通常の非並列テストを使用すると、引き続き正常に機能しますが、並列モードに切り替えると、テーブルが見つからないというエラーが発生します。
LS55321 2016年

@LeeSemelを並列モードで使用する場合、おそらくrlmvのソリューションを使用することになります
Guillaume Vincent

@guillaumevincent並列モードでdjango-test-without-migrationsを使用すると、同じ問題が発生します
LS55321


3

更新:気にしないでください。この変更は1.10 finalがリリースされる前に戻されました。うまくいけば、それは将来のバージョンで戻ってくるでしょう。


Django 1.10以降、これはテストデータベースの設定で制御できることに注意してください。

移行する

デフォルト: True

に設定するとFalse、Djangoは移行を使用してテストデータベースを作成しません。



1

django 1.9以降では、Guillaume Vincentの答えが機能しなくなったため、新しいソリューションを次に示します。

の定義後、設定ファイルでこのスニペットを使用しています INSTALLED_APPS

if os.environ.get('TESTS_WITHOUT_MIGRATIONS', False):
    MIGRATION_MODULES = {
        app.split('.')[-1]: None for app in INSTALLED_APPS
    }

インストールされているすべてのアプリを反復処理し、それぞれに移行モジュールがないとマークします。詳細については、djangoのドキュメントを参照してください

このスニペットを使用すると、環境変数を設定してテストを実行できます TESTS_WITHOUT_MIGRATIONS。例:

TESTS_WITHOUT_MIGRATIONS=1 ./manage.py test

1

私はdjango 1.10以降の移行を無効にする方法を理解しています、誰かのために役立つかもしれません。ここにgitのリンクがあります

class DisableMigrations(dict):
    def __contains__(self, item):
        return True

    def __getitem__(self, item):
        return None

DATABASES = DisableMigrations()

MIGRATION_MODULES = DisableMigrations()

django 1.10の移行には2つの部分があります。load_diskレコーダー

一部load_diskで添加してもアプリの移行モデル用INSTALL_APP の一部recorder我々が設定する必要が1.9以前のバージョンのデータベース接続のためのMIGRATION_MODULES={'do.not.migrate':'notmigrations'}テストを実行しているとき、今、私たちはそれをのようなどれも設定されていない必要がMIGRATION_MODULES={'do.not.migrate':None} 、我々はすべてのアプリのためのメイクの移行を望んでいないのであればを、dictを拡張しNonegetitemfunctionに戻るだけで、同じDATABASESことをで実行する必要があります。

PS:コマンドの場合--setting=module.path.settings_test_snippettest PPSの後に指定する必要があります。で作業している場合はpycharm、で オプションを設定せず、カスタム設定でのパスを追加するだけです。それだけで大丈夫!!--settingsRun/Debug configurationssettings_test_snippet.py

楽しい

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.