Saya menggunakan pelari tes berbasis unit test sederhana untuk menguji aplikasi Django saya.
Aplikasi saya sendiri dikonfigurasi untuk menggunakan logger dasar di settings.py menggunakan:
logging.basicConfig(level=logging.DEBUG)
Dan dalam kode aplikasi saya menggunakan:
logger = logging.getLogger(__name__)
logger.setLevel(getattr(settings, 'LOG_LEVEL', logging.DEBUG))
Namun, saat menjalankan unittests, saya ingin menonaktifkan pencatatan agar tidak mengacaukan hasil pengujian saya. Apakah ada cara sederhana untuk mematikan proses masuk secara global, sehingga penebang khusus aplikasi tidak menulis hal-hal ke konsol ketika saya menjalankan tes?
python
django
unit-testing
logging
shreddd
sumber
sumber
Jawaban:
akan menonaktifkan semua panggilan logging dengan level yang tidak terlalu parah atau sama dengan
CRITICAL
. Logging dapat diaktifkan kembali dengansumber
logging.disable
(dari jawaban yang diterima) di bagian atastests.py
dalam aplikasi Anda yang melakukan pencatatan.tearDown()
metode Anda :logging.disable(logging.NOTSET)
menempatkan logging kembali ke tempatnya dengan rapi.tests
modul ini sangat berguna.Karena Anda berada di Django, Anda dapat menambahkan baris ini ke settings.py Anda:
Dengan begitu Anda tidak perlu menambahkan baris itu di setiap
setUp()
tes Anda.Anda juga dapat melakukan beberapa perubahan praktis untuk kebutuhan pengujian Anda dengan cara ini.
Ada cara "lebih baik" atau "bersih" lainnya untuk menambahkan spesifik ke tes Anda dan itu adalah membuat pelari tes Anda sendiri.
Cukup buat kelas seperti ini:
Dan sekarang tambahkan ke file settings.py Anda:
Ini memungkinkan Anda melakukan satu modifikasi yang sangat berguna yang tidak dilakukan oleh pendekatan lain, yaitu membuat Django hanya menguji aplikasi yang Anda inginkan. Anda dapat melakukannya dengan mengubah
test_labels
menambahkan baris ini ke pelari uji:sumber
Jawaban lain mencegah "menulis hal-hal ke konsol" dengan secara global menetapkan infrastruktur logging untuk mengabaikan apa pun. Ini bekerja tetapi saya merasa terlalu tumpul pendekatan. Pendekatan saya adalah melakukan perubahan konfigurasi yang hanya melakukan apa yang diperlukan untuk mencegah log keluar di konsol. Jadi saya menambahkan filter pencatatan khusus ke
settings.py
:Dan saya mengkonfigurasi Django logging untuk menggunakan filter:
Hasil akhir: ketika saya menguji, tidak ada yang masuk ke konsol, tetapi semuanya tetap sama.
Kenapa melakukan ini?
Saya mendesain kode yang berisi instruksi logging yang dipicu hanya dalam keadaan tertentu dan yang akan menghasilkan data yang tepat yang saya butuhkan untuk diagnosis jika ada kesalahan. Oleh karena itu saya menguji bahwa mereka melakukan apa yang seharusnya mereka lakukan dan dengan demikian sepenuhnya menonaktifkan logging tidak layak bagi saya. Saya tidak ingin menemukan begitu perangkat lunak dalam produksi bahwa apa yang saya pikir akan dicatat tidak dicatat.
Selain itu, beberapa pelari uji (Hidung, misalnya) akan menangkap log selama pengujian dan output bagian yang relevan dari log bersama dengan kegagalan pengujian. Berguna untuk mencari tahu mengapa suatu tes gagal. Jika logging sepenuhnya dimatikan, maka tidak ada yang bisa ditangkap.
sumber
test_settings.py
file yang berada di sebelah proyek sayasettings.py
. Sudah diatur untuk memuatsettings.py
dan membuat beberapa perubahan seperti diaturTESTING_MODE
keTrue
. Pelari ujian saya diatur sehinggatest_settings
modul dimuat untuk pengaturan proyek Django. Ada banyak cara yang bisa dilakukan. Saya biasanya pergi dengan mengatur variabel lingkunganDJANGO_SETTINGS_MODULE
keproj.test_settings
.Saya menyukai ide pelari uji coba Hassek. Perlu dicatat bahwa
DjangoTestSuiteRunner
tidak ada lagi runner tes default di Django 1.6+, telah digantikan olehDiscoverRunner
. Untuk perilaku default, pelari ujian harus lebih seperti:sumber
helpers
, yang hanya memiliki utilitas yang tidak mengimpor dari tempat lain di dalam proyek.Saya telah menemukan bahwa untuk pengujian dalam
unittest
atau sejenisnya kerangka kerja, cara paling efektif untuk menonaktifkan dengan aman masuk logging unit yang tidak diinginkan adalah untuk mengaktifkan / menonaktifkan dalamsetUp
/tearDown
metode kasus uji tertentu. Ini memungkinkan satu target khusus di mana log harus dinonaktifkan. Anda juga bisa melakukan ini secara eksplisit di logger dari kelas yang Anda uji.sumber
Saya menggunakan dekorator metode sederhana untuk menonaktifkan logging hanya dalam metode pengujian tertentu.
Dan kemudian saya menggunakannya seperti dalam contoh berikut:
sumber
Ada beberapa metode yang cantik dan bersih untuk menangguhkan proses masuk dengan
unittest.mock.patch
metode tes .foo.py :
tests.py :
Dan tidak
python3 -m unittest tests
akan menghasilkan keluaran logging.sumber
Terkadang Anda ingin log dan terkadang tidak. Saya memiliki kode ini di
settings.py
Jadi, jika Anda menjalankan tes dengan
--no-logs
opsi, Anda hanya akan mendapatkancritical
log:Ini sangat membantu jika Anda ingin mempercepat tes pada aliran integrasi berkelanjutan Anda.
sumber
Jika Anda tidak ingin itu berkali-kali nyalakan / matikan di setUp () dan tearDown () untuk unittest (tidak melihat alasan untuk itu), Anda bisa melakukannya sekali per kelas:
sumber
Dalam kasus di mana saya ingin sementara waktu menekan logger tertentu, saya telah menulis manajer konteks kecil yang saya temukan berguna:
Anda kemudian menggunakannya seperti:
Ini memiliki keuntungan bahwa logger diaktifkan kembali (atau diatur kembali ke keadaan sebelumnya) setelah
with
selesai.sumber
Anda dapat menempatkan ini di direktori tingkat atas untuk
__init__.py
file unit test . Ini akan menonaktifkan logging secara global di unit test suite.sumber
Dalam kasus saya, saya memiliki file pengaturan yang
settings/test.py
dibuat khusus untuk tujuan pengujian, begini tampilannya:Saya menempatkan variabel lingkungan
DJANGO_SETTINGS_MODULE=settings.test
ke/etc/environment
.sumber
Jika Anda memiliki modul initaliser yang berbeda untuk pengujian, pengembangan, dan produksi, maka Anda dapat menonaktifkan apa pun atau mengalihkannya di server awal. Saya memiliki local.py, test.py dan production.py yang semuanya mewarisi dari common.y
common.py melakukan semua konfigurasi utama termasuk cuplikan ini:
Kemudian di test.py saya punya ini:
Ini menggantikan pengendali konsol dengan FileHandler dan berarti masih mendapatkan logging tapi saya tidak harus menyentuh basis kode produksi.
sumber
Jika Anda menggunakan
pytest
:Karena pytest menangkap pesan log dan hanya menampilkannya untuk pengujian yang gagal, Anda biasanya tidak ingin menonaktifkan logging. Alih-alih, gunakan
settings.py
file terpisah untuk pengujian (mis.,test_settings.py
), Dan tambahkan ke dalamnya:Ini memberitahu Django untuk melewatkan mengkonfigurasi logging sama sekali. Itu
LOGGING
pengaturan akan diabaikan dan dapat dihapus dari pengaturan.Dengan pendekatan ini, Anda tidak mendapatkan logging untuk tes yang lulus, dan Anda mendapatkan semua logging untuk tes yang gagal.
Tes akan berjalan menggunakan pencatatan yang diatur oleh
pytest
. Ini dapat dikonfigurasi sesuai dengan keinginan Anda dipytest
pengaturan (misalnya,tox.ini
). Untuk memasukkan pesan log level debug, gunakanlog_level = DEBUG
(atau argumen baris perintah yang sesuai).sumber