Nonaktifkan migrasi saat menjalankan pengujian unit di Django 1.7

110

Django 1.7 memperkenalkan migrasi basis data .

Saat menjalankan pengujian unit di Django 1.7, ini memaksa migrasi , yang membutuhkan waktu lama. Jadi saya ingin melewatkan migrasi django, dan membuat database pada kondisi akhir.

Saya tahu bahwa mengabaikan migrasi bisa menjadi praktik yang buruk, karena bagian kode itu tidak akan diuji. Tapi bukan itu masalahnya: Saya menjalankan migrasi penuh di server pengujian CI (jenkins). Saya hanya ingin melewatkan migrasi dalam pengujian lokal saya, yang mengutamakan kecepatan.


Beberapa konteks:

Hingga Django 1.6 , ketika menggunakan Selatan, saya menggunakan pengaturan SOUTH_TESTS_MIGRATE :

Secara default, perintah syncdb South juga akan menerapkan migrasi jika dijalankan dalam mode non-interaktif, termasuk saat Anda menjalankan pengujian - perintah ini akan menjalankan setiap migrasi setiap kali Anda menjalankan pengujian.

Jika Anda ingin runner pengujian menggunakan syncdb daripada migrasi - misalnya, jika migrasi Anda memakan waktu terlalu lama untuk diterapkan - cukup setel SOUTH_TESTS_MIGRATE = False di settings.py.

Namun, syncdb tidak ada lagi, sekarang sudah dimigrasi .

Dan dari Django 1.8 saya akan menggunakan parameter --keepdb :

Opsi --keepdb dapat digunakan untuk mempertahankan database pengujian di antara pengujian yang dijalankan. Keuntungannya adalah melewatkan tindakan buat dan penghancuran yang sangat mengurangi waktu untuk menjalankan pengujian, terutama yang ada dalam rangkaian pengujian yang besar. Jika database pengujian tidak ada, database akan dibuat saat dijalankan pertama kali dan kemudian dipertahankan untuk setiap proses berikutnya. Migrasi apa pun yang belum diterapkan juga akan diterapkan ke database pengujian sebelum menjalankan rangkaian pengujian.

Jadi pertanyaan ini terbatas pada Django 1.7.

David Arcos
sumber
Saya berpendapat bahwa selama UT, Anda benar-benar tidak menjalankan migrasi dengan cara yang mengujinya karena DB yang Anda gunakan untuk memulai tidak ada. Menguji migrasi benar-benar hanya terjadi ketika Anda memigrasi DB yang ada. Bisnis migrasi 1,7 ini adalah duri nyata pertama di bawah pelana yang saya alami dengan Django, tapi ini sangat mengganggu. Selatan setidaknya mendapatkan skenario pengujian yang tepat untuk migrasi.
boatcoder
The django-test-without-migrationspaket telah benar-benar berguna bagi saya, Anda mungkin ingin mengubah jawaban yang diterima untuk stackoverflow.com/a/28993456/200224
Andy
Saya lebih suka menghindari penambahan dependensi baru, jika memungkinkan.
David Arcos

Jawaban:

79

Lihat solusi ini , diposting oleh Bernie Sumption ke milis pengembang Django:

Jika makemigrations belum dijalankan, perintah "migrate" akan memperlakukan aplikasi sebagai tidak bermigrasi, dan membuat tabel langsung dari model seperti yang dilakukan syncdb di 1.6. Saya mendefinisikan modul pengaturan baru hanya untuk pengujian unit yang disebut "settings_test.py", yang mengimpor * dari modul pengaturan utama dan menambahkan baris ini:

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

Lalu saya menjalankan tes seperti ini:

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

Orang bodoh ini bermigrasi ke dalam pemikiran bahwa aplikasi tidak dimigrasi, sehingga setiap kali database pengujian dibuat, itu mencerminkan struktur saat ini dari models.py.

Dalam Django 1.9, situasi ini agak ditingkatkan , dan Anda dapat menyetel nilainya ke None:

MIGRATION_MODULES = {"myapp": Tidak Ada}

albertgasset.dll
sumber
9
Perhatikan bahwa myapp.migrations_not_used_in_testsmodul seharusnya tidak ada.
bmihelac
4
Selain komentar @bmihelac yang dibuat tentang modul yang tidak ada, string modul harus berisi 'migrasi' substring, Untuk alasannya lihat: github.com/django/django/blob/stable/1.7.x/django/db/migrations /…
nealtodd
7
Inti dari fungsi untuk membangun MIGRATION_MODULES secara dinamis di settings_test.py: gist.github.com/nealtodd/2869341f38f5b1eeb86d
nealtodd
1
TY. Saya dapat mengurangi pengujian unit saya dari 13 detik menjadi 4 detik karena ini. Selain itu, peningkatan kecepatan lebih dapat ditemukan dengan menggunakan sqlite untuk pengujian. Bagi saya, menggunakan postgres untuk tes membutuhkan 5,5 detik tetapi sqlite membutuhkan 4 detik.
Gattster
21
Dari komentar inti @ nealtodd berikut ini tautan ke solusi yang menghindari beberapa jebakan dan sangat sederhana: gist.github.com/NotSqrt/5f3c76cd15e40ef62d09
djsutho
72

Inilah akhir dari file pengaturan saya:

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()

berdasarkan potongan ini

Saya menonaktifkan migrasi hanya ketika tes sedang berjalan

Guillaume Vincent
sumber
1
Bagus! Saya akan menambahkan __setitem__(self, *_)metode juga karena kami memiliki masalah dengan aplikasi yang mengatur migrasi mereka sendiri seperti settings.MIGRATION_MODULES['chroniker'] = 'db_migrations'
Zhe Li
1
Terima kasih banyak untuk ini, ini satu-satunya hal yang saya temukan yang benar-benar berfungsi.
fluffels
Ini tidak lagi bekerja pada Django 1.9 ketika menjalankan percobaan dalam mode paralel. Menggunakan pengujian non-paralel normal, ini terus berfungsi dengan baik, tetapi beralih ke mode paralel menghasilkan kesalahan yang tabel tidak ditemukan.
LS55321
@LeeSemel dalam mode paralel Anda mungkin ingin menggunakan solusi dari rlmv
Guillaume Vincent
@guillaumevincent saya memiliki masalah yang sama ketika menggunakan django-test-without-migrations dalam mode paralel
LS55321
3

Memperbarui : Tidak apa-apa, perubahan ini dikembalikan sebelum final 1,10 dirilis. Semoga ini akan kembali di versi yang akan datang.


Perhatikan bahwa pada Django 1.10 ini dapat dikontrol oleh pengaturan basis data percobaan.

MIGRASI

Default: True

Jika disetel ke False, Django tidak akan menggunakan migrasi untuk membuat basis data percobaan.

Kevin Christopher Henry
sumber
1

Untuk django 1.9 dan yang lebih baru, jawaban Guillaume Vincent tidak berfungsi lagi, jadi inilah solusi baru:

Saya menggunakan potongan ini di file pengaturan saya, setelah definisi dari INSTALLED_APPS

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

Ini mengulangi semua aplikasi yang diinstal dan menandai masing-masing sebagai tidak memiliki modul migrasi. Lihat dokumen django untuk informasi lebih lanjut .

Dengan menggunakan potongan ini Anda dapat menjalankan pengujian Anda, mengatur variabel lingkungan TESTS_WITHOUT_MIGRATIONS, misalnya:

TESTS_WITHOUT_MIGRATIONS=1 ./manage.py test
devsnd
sumber
1

Saya baru saja memikirkan bagaimana menonaktifkan migrasi setelah django 1.10, semoga bisa membantu seseorang. Ini tautan di git

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

    def __getitem__(self, item):
        return None

DATABASES = DisableMigrations()

MIGRATION_MODULES = DisableMigrations()

Migrasi untuk django 1.10 memiliki dua bagian, lihat load_disk dan perekam

Bagian dari load_diskuntuk model migrasi aplikasi yang ditambahkan di INSTALL_APP Dan bagian dari recorderuntuk koneksi database Untuk versi sebelum 1.9 kita perlu mengatur MIGRATION_MODULES={'do.not.migrate':'notmigrations'}saat Anda menjalankan tes Sekarang kita perlu mengaturnya Tidak ada sepertiMIGRATION_MODULES={'do.not.migrate':None} Jadi jika kita tidak ingin melakukan migrasi untuk aplikasi apa pun , hanya memperpanjang dict dan kembali Noneuntuk getitemfungsi, dan melakukan hal yang sama diDATABASES , itu adalah hal yang benar perlu Anda lakukan

PS: Untuk perintah, Anda perlu menentukan --setting=module.path.settings_test_snippetsetelah test PPS Jika Anda bekerja dengan pycharm, jangan setel --settings opsi diRun/Debug configurations , cukup tambahkan jalursettings_test_snippet.py di pengaturan Kustom. Itu baik-baik saja !!

Nikmati

FavorMylikes
sumber