Apakah ada kemungkinan untuk menulis django unittests tanpa membuat db? Saya ingin menguji logika bisnis yang tidak memerlukan pengaturan db. Dan sementara itu cepat untuk mengatur db, saya benar-benar tidak membutuhkannya dalam beberapa situasi.
126
Jawaban:
Anda dapat mensubklasifikasikan DjangoTestSuiteRunner dan mengganti metode setup_databases dan teardown_databases untuk dilewati.
Buat file pengaturan baru dan atur TEST_RUNNER ke kelas baru yang baru saja Anda buat. Kemudian ketika Anda menjalankan tes Anda, tentukan file pengaturan baru Anda dengan flag --settings.
Inilah yang saya lakukan:
Buat pelari setelan ujian khusus yang mirip dengan ini:
Buat pengaturan khusus:
Saat Anda menjalankan tes, jalankan seperti berikut ini dengan --settings flag diset ke file pengaturan baru Anda:
PEMBARUAN: April / 2018
Sejak Django 1.8, modul dipindahkan ke .
django.test.simple.DjangoTestSuiteRunner
'django.test.runner.DiscoverRunner'
Untuk info lebih lanjut, periksa bagian dokumen resmi tentang pelari ujian khusus.
sumber
--testrunner
opsi.Secara umum tes dalam suatu aplikasi dapat diklasifikasikan ke dalam dua kategori
Django mendukung pengujian unit dan integrasi.
Unit test, tidak perlu melakukan setup dan meruntuhkan basis data dan ini harus kita warisi dari SimpleTestCase .
Untuk kasus uji integrasi, mewarisi dari TestCase pada gilirannya mewarisi dari TransactionTestCase dan itu akan mengatur dan meruntuhkan database sebelum menjalankan setiap tes.
Strategi ini akan memastikan bahwa basis data dibuat dan dimusnahkan hanya untuk kasus uji yang mengakses database dan karenanya pengujian akan lebih efisien
sumber
Dari
django.test.simple
Jadi
DiscoverRunner
ganti alih-alihDjangoTestSuiteRunner
.Gunakan seperti itu:
sumber
Saya memilih untuk mewarisi
django.test.runner.DiscoverRunner
dan membuat beberapa tambahan kerun_tests
metode ini.Penambahan pertama saya memeriksa apakah pengaturan db diperlukan dan memungkinkan
setup_databases
fungsi normal untuk memulai jika db diperlukan. Tambahan kedua saya memungkinkan normalteardown_databases
untuk berjalan jikasetup_databases
metode itu diizinkan untuk dijalankan.Kode saya mengasumsikan bahwa setiap TestCase yang mewarisi dari
django.test.TransactionTestCase
(dan dengan demikiandjango.test.TestCase
) memerlukan database yang harus disiapkan. Saya membuat asumsi ini karena dokumen Django mengatakan:https://docs.djangoproject.com/en/1.6/topics/testing/tools/#django.test.SimpleTestCase
mysite / scripts / settings.py
Akhirnya, saya menambahkan baris berikut ke file settings.py proyek saya.
mysite / settings.py
Sekarang, ketika menjalankan hanya tes yang tidak bergantung db, suite pengujian saya menjalankan urutan besarnya lebih cepat! :)
sumber
Diperbarui: lihat juga jawaban ini untuk menggunakan alat pihak ketiga
pytest
.@ Caesar benar. Setelah berjalan secara tidak sengaja
./manage.py test --settings=no_db_settings
, tanpa menentukan nama aplikasi, basis data pengembangan saya terhapus.Untuk cara yang lebih aman, gunakan hal yang sama
NoDbTestRunner
, tetapi dalam hubungannya dengan yang berikutmysite/no_db_settings.py
:Anda perlu membuat database yang disebut
_test_mysite_db
menggunakan alat basis data eksternal. Kemudian jalankan perintah berikut untuk membuat tabel terkait:Jika Anda menggunakan Selatan, jalankan juga perintah berikut:
BAIK!
Anda sekarang dapat menjalankan tes unit dengan sangat cepat (dan aman) dengan:
sumber
Sebagai alternatif untuk memodifikasi pengaturan Anda untuk membuat NoDbTestRunner "aman", inilah versi modifikasi dari NoDbTestRunner yang menutup koneksi database saat ini dan menghapus informasi koneksi dari pengaturan dan objek koneksi. Berfungsi untuk saya, ujilah di lingkungan Anda sebelum mengandalkannya :)
sumber
__getitem__
lagi. Gunakanconnections._connections.default
untuk mengakses objek.Solusi lain adalah dengan membuat kelas tes Anda hanya mewarisi dari
unittest.TestCase
bukan kelas tes Django. Dokumen Django ( https://docs.djangoproject.com/en/2.0/topics/testing/overview/#writing-tests ) berisi peringatan berikut ini:Namun, jika tes Anda tidak menggunakan database, peringatan ini tidak perlu Anda khawatirkan dan Anda dapat menuai manfaat karena tidak harus menjalankan setiap kasus uji dalam transaksi.
sumber
Solusi di atas juga baik-baik saja. Tetapi solusi berikut ini juga akan mengurangi waktu pembuatan db jika ada lebih banyak jumlah migrasi. Selama pengujian unit, menjalankan syncdb alih-alih menjalankan semua migrasi selatan akan jauh lebih cepat.
sumber
Host web saya hanya memungkinkan membuat dan menjatuhkan basis data dari GUI Web mereka, jadi saya mendapatkan kesalahan "Mendapat kesalahan saat membuat basis data pengujian: Izin ditolak" ketika mencoba menjalankan
python manage.py test
.Saya berharap untuk menggunakan opsi --keepdb untuk django-admin.py tetapi sepertinya tidak didukung lagi pada Django 1.7.
Yang akhirnya saya lakukan adalah memodifikasi kode Django di ... / django / db / backends / creation.py, khususnya fungsi _create_test_db dan _destroy_test_db.
Karena
_create_test_db
saya berkomentar keluarcursor.execute("CREATE DATABASE ...
garis dan menggantinya denganpass
begitutry
blok tidak akan kosong.Karena
_destroy_test_db
saya baru saja berkomentarcursor.execute("DROP DATABASE
- saya tidak perlu menggantinya dengan apa pun karena sudah ada perintah lain di blok (time.sleep(1)
).Setelah itu pengujian saya berjalan dengan baik - walaupun saya telah membuat versi test_ dari database reguler saya secara terpisah.
Ini bukan solusi yang bagus tentu saja, karena akan rusak jika Django ditingkatkan, tapi saya punya salinan lokal Django karena menggunakan virtualenv jadi setidaknya saya memiliki kendali atas kapan / jika saya meng-upgrade ke versi yang lebih baru.
sumber
Solusi lain yang tidak disebutkan: ini mudah bagi saya untuk mengimplementasikan karena saya sudah memiliki banyak file pengaturan (untuk lokal / pementasan / produksi) yang mewarisi dari base.py. Jadi tidak seperti orang lain, saya tidak perlu menimpa DATABASES ['default'], karena DATABASES tidak diset di base.py
SimpleTestCase masih mencoba untuk terhubung ke database pengujian saya dan menjalankan migrasi. Ketika saya membuat file config / settings / test.py yang tidak mengatur DATABASES untuk apa pun, maka pengujian unit saya berjalan tanpa itu. Itu memungkinkan saya untuk menggunakan model yang memiliki kunci asing dan bidang kendala unik. (Membalikkan pencarian kunci asing, yang membutuhkan pencarian db, gagal.)
(Django 2.0.6)
Cuplikan kode PS
sumber
Saat menggunakan pelari tes hidung (django-nose), Anda dapat melakukan sesuatu seperti ini:
my_project/lib/nodb_test_runner.py
:Di Anda,
settings.py
Anda dapat menentukan pelari tes di sana, yaituTEST_RUNNER = 'lib.nodb_test_runner.NoDbTestRunner' . # Was 'django_nose.NoseTestSuiteRunner'
ATAU
Saya menginginkannya untuk menjalankan tes tertentu saja, jadi saya menjalankannya seperti ini:
sumber