[ English | 中文 (简体, 中国) | русский | português (Brasil) | नेपाली | 한국어 (대한민국) | Indonesia | français | español | esperanto | English (United Kingdom) | Deutsch ]

Tinjauan Pengujian

Memiliki tes yang baik di tempat sangat penting untuk memastikan basis kode yang stabil dan dapat dipelihara. Semoga itu tidak perlu penjelasan lagi.

Namun, apa yang mendefinisikan tes "good" tidak selalu jelas, dan ada banyak kesulitan umum yang dapat dengan mudah mengagalkan suite tes Anda.

Jika Anda sudah mengetahui segala sesuatu tentang pengujian tetapi muak dengan mencoba men-debug mengapa tes tertentu gagal, Anda dapat melewati intro dan langsung melompat ke Tes Unit Debugging.

Ikhtisar pengujian

Ada tiga jenis tes utama, masing-masing dengan pro dan kontra terkait:

Tes unit

Ini adalah tes terisolasi yang berdiri sendiri tanpa ketergantungan eksternal. Mereka ditulis dari perspektif "knowing the code", dan menguji asumsi basis kode dan pengembang.

Pros:

  • Umumnya ringan dan cepat.

  • Dapat dijalankan di mana saja, kapan saja karena mereka tidak memiliki dependensi eksternal.

Cons:

  • Mudah longgar dalam menulisnya, atau malas membangunnya.

  • Tidak dapat menguji interaksi dengan layanan eksternal langsung.

Tes fungsional

Ini umumnya juga merupakan tes yang terisolasi, meskipun terkadang mereka dapat berinteraksi dengan layanan lain yang berjalan secara lokal. Perbedaan utama antara tes fungsional dan tes unit, adalah bahwa tes fungsional ditulis dari sudut pandang pengguna (yang tidak tahu apa-apa tentang kode) dan hanya tahu apa yang mereka masukkan dan apa yang mereka dapatkan kembali. Pada dasarnya ini adalah pengujian tingkat lebih tinggi dari "does the result match the spec?".

Pros:

  • Pastikan kode Anda always memenuhi persyaratan fungsional yang dinyatakan.

  • Memverifikasi hal-hal dari perspektif "end user", yang membantu memastikan pengalaman berkualitas tinggi.

  • Merancang kode Anda dengan mempertimbangkan perspektif pengujian fungsional membantu menjaga sudut pandang tingkat yang lebih tinggi dalam pikiran.

Cons:

  • Membutuhkan lapisan pemikiran tambahan untuk mendefinisikan persyaratan fungsional dalam hal input dan output.

  • Seringkali membutuhkan penulisan serangkaian tes terpisah dan/atau menggunakan kerangka kerja pengujian yang berbeda dari tes unit Anda.

  • Tidak menawarkan wawasan apa pun tentang kualitas atau status kode yang mendasarinya, hanya memverifikasi bahwa kode itu berfungsi atau tidak.

Tes Integrasi

Lapisan pengujian ini melibatkan pengujian semua komponen yang berinteraksi atau bergantung pada basis kode Anda bersamaan. Ini sama dengan pengujian "live", tetapi dengan cara yang berulang.

Pros:

  • Menangkap many bug yang tidak akan diuji unit dan fungsional.

  • Tidak mengandalkan asumsi tentang input dan output.

  • Akan memperingatkan Anda ketika perubahan komponen eksternal merusak kode Anda.

  • Akan mengambil screenshot dari halaman saat ini pada pengujian gagal untuk debug mudah

Cons:

  • Sulit dan menyita waktu untuk menciptakan lingkungan pengujian yang berulang.

  • Apakah saya menyebutkan bahwa pengaturannya itu menyakitkan?

Direktori screenshot dapat diatur melalui file horizon.conf, nilai default: ./integration_tests_screenshots

Jadi apa yang harus saya tulis?

Beberapa pedoman sederhana:

  1. Setiap perbaikan bug harus memiliki tes regresi. Periode.

  2. Saat menulis fitur baru, pikirkan tentang menulis unit test untuk memverifikasi perilaku langkah demi langkah saat Anda menulis fitur. Setiap kali Anda menjalankan kode Anda dengan tangan dan memverifikasinya secara manual, pikirkan "could I write a test to do this instead?". Dengan begitu ketika fitur selesai dan Anda siap untuk melakukan itu, Anda sudah memiliki seluruh rangkaian tes yang lebih menyeluruh daripada apa pun yang Anda tulis setelah fakta.

  3. Tulis tes yang mengenai setiap tampilan di aplikasi Anda. Bahkan jika mereka tidak menyatakan satu hal pun tentang kode tersebut, ia memberi tahu Anda bahwa pengguna Anda tidak mendapatkan kesalahan fatal hanya dengan berinteraksi dengan kode Anda.

Apa yang membuat unit test bagus?

Membatasi fokus kami hanya untuk pengujian unit, ada sejumlah hal yang dapat Anda lakukan untuk membuat tes unit Anda bermanfaat, dapat dipertahankan, dan tidak memberatkan sebanyak mungkin.

Uji data

Gunakan satu set, data uji yang konsisten. Tumbuhkan dari waktu ke waktu, tetapi lakukan segala yang Anda bisa untuk tidak memecahnya. Dengan cepat menjadi tidak dapat dipelihara dan tidak sinkron dengan kenyataan.

Jadikan data pengujian Anda seakurat mungkin dengan kenyataan. Berikan all atribut suatu objek, berikan objek di semua berbagai negara bagian yang mungkin ingin Anda uji.

Jika Anda melakukan saran pertama di atas first itu membuat yang kedua jauh lebih tidak menyakitkan. Tulis sekali, gunakan di mana-mana.

Untuk membuat hidup Anda lebih mudah, jika basis kode Anda tidak memiliki built-in ORM-like function untuk mengelola data pengujian Anda, Anda dapat mempertimbangkan untuk membangun (atau meminjam) sendiri. Mampu melakukan kueri pengambilan sederhana pada data pengujian Anda sangat berharga.

Mocking

Mocking adalah praktik menyediakan pengamanan untuk objek atau potongan kode yang tidak perlu Anda uji. Meskipun nyaman, mereka harus digunakan dengan hati-hati extreme.

Mengapa? Karena terlalu sering mock bisa dengan cepat membuat Anda dalam situasi di mana Anda tidak menguji kode nyata. Semua yang telah Anda lakukan diverifikasi bahwa kerangka kerja mocking Anda mengembalikan apa yang Anda katakan. Masalah ini bisa sangat sulit dikenali, karena Anda mungkin mocking hal-hal dalam metode setUp, modul lain, dll.

Aturan praktis yang baik adalah mock sedekat mungkin dengan sumbernya. Jika Anda memiliki panggilan fungsi yang memanggil API eksternal dalam tampilan, mock out API eksternal, bukan seluruh fungsi. Jika Anda mock seluruh fungsi Anda tiba-tiba kehilangan cakupan tes untuk seluruh potongan kode inside codebase Anda. Potong ikatan dengan benar di tempat sistem Anda berakhir dan dunia eksternal dimulai.

Demikian pula, jangan mock nilai pengembalian ketika Anda bisa membangun nilai pengembalian nyata dari jenis yang benar dengan atribut yang benar. Anda hanya menambahkan titik kegagalan potensial lainnya dengan menggunakan kerangka kerja mock Anda daripada kode sungguhan. Mengikuti saran untuk pengujian di atas akan membuat ini jauh lebih tidak memberatkan.

Penegasan dan verifikasi

Pikirkan panjang dan keras tentang apa yang benar-benar ingin Anda verifikasi dalam pengujian unit Anda. Secara khusus, pikirkan logika kustom apa yang dijalankan oleh kode Anda.

Jebakan (pitfall) yang umum adalah mengambil objek uji yang diketahui, meneruskannya melalui kode Anda, dan kemudian memverifikasi properti objek itu pada output. Ini semua baik dan bagus, kecuali jika Anda memverifikasi properti yang tidak tersentuh oleh kode Anda. Yang ingin Anda periksa adalah bagian-bagian yang changed, added, atau removed. Jangan periksa atribut id objek kecuali Anda memiliki alasan untuk curiga itu bukan objek yang Anda mulai. Tetapi jika Anda menambahkan atribut baru ke dalamnya, yakinlah Anda memverifikasi yang keluar benar.

Juga sangat umum untuk menghindari pengujian hal-hal yang benar-benar Anda pedulikan karena itu lebih sulit. Memverifikasi bahwa pesan yang tepat ditampilkan kepada pengguna setelah tindakan, menguji kesalahan formulir, memastikan penanganan pengecualian diuji ... hal-hal semacam ini tidak selalu mudah, tetapi sangat perlu.

Untuk itu, Horizon menyertakan beberapa pernyataan khusus untuk mempermudah tugas-tugas ini. assertNoFormErrors(), assertMessageCount(), dan assertNoMessages() semua ada untuk tujuan ini. Selain itu, mereka memberikan hasil yang bermanfaat ketika terjadi kesalahan sehingga Anda tidak perlu menggaruk kepala bertanya-tanya mengapa uji tampilan Anda tidak mengarahkan seperti yang diharapkan ketika Anda memposting formulir.

Tes Unit Debugging

Kiat dan trik

  1. Gunakan :meth: ~ openstack_dashboard.test.helpers.TestCase.assertNoFormErrors segera setelah panggilan client.post Anda untuk pengujian yang menangani tampilan formulir. Ini akan segera gagal jika formulir POST Anda gagal karena kesalahan validasi dan memberi tahu Anda apa kesalahannya.

  2. Gunakan :meth: ~ horizon.test.helpers.TestCase.assertMessageCount dan :meth:` ~ horizon.test.helpers.TestCase.assertNoMessages` saat sepotong kode gagal dijelaskan secara tidak dapat dijelaskan. Karena penangan kesalahan inti melampirkan pesan kesalahan yang dihadapi pengguna (dan karena pencatatan inti dibungkam selama pengujian berjalan) metode ini memberi Anda manfaat ganda memverifikasi keluaran yang Anda harapkan sambil dengan jelas menunjukkan kepada Anda pesan kesalahan yang bermasalah jika gagal.

  3. Gunakan modul pdb Python secara bebas. Banyak orang tidak menyadari itu berfungsi dengan baik dalam kasus uji seperti halnya dalam tampilan langsung. Cukup masukkan import pdb; pdb.set_trace() di mana pun di basis kode Anda akan menjatuhkan penerjemah ke shell interaktif sehingga Anda dapat menjelajahi lingkungan pengujian Anda dan melihat asumsi Anda tentang kode yang sebenarnya tidak benar sempurna.

  4. Jika kesalahan ada di suite uji Selenium, Anda kemungkinan akan mendapatkan sedikit informasi tentang kesalahan tersebut. Untuk menambah informasi yang diberikan kepada Anda, edit horizon/test/settings.py untuk mengatur DEBUG = True dan atur level logging ke 'DEBUG' untuk logger 'test' default. Juga, tambahkan konfigurasi logger untuk Django :

         },
         'loggers': {
    +        'django': {
    +            'handlers': ['test'],
    +            'propagate': False,
    +        },
             'django.db.backends': {
    

Pengujian dengan berbagai versi Django

Horizon mendukung beberapa versi Django dan CI kami menguji patch yang diusulkan dengan berbagai versi Django yang didukung. Nama-nama pekerjaan yang sesuai seperti horizon-tox-python3-django111.

Anda dapat mengetahui versi tox env dan django mana yang digunakan dengan memeriksa tox_envlist dan django_version dari definisi pekerjaan terkait di .zuul.yaml.

Untuk mengujinya secara lokal, Anda memerlukan beberapa langkah tambahan. Berikut ini contohnya tox_envlist adalah py36 dan django_version adalah >=1.11,<2.0.

$ tox -e py36 --notest -r
$ .tox/py36/bin/python -m pip install 'django>=1.11,<2.0'
$ tox -e py36

Catatan

  • ``-r``di perintah pertama menciptakan lingkungan toks. Hilangkan jika Anda tahu apa yang terjadi.

  • Kita biasanya perlu mengutip versi Django di baris perintah pip di sebagian besar shell untuk menghindari interpretasi oleh shell.

Untuk memeriksa versi Django yang terinstal di tox env Anda, jalankan:

$ .tox/py36/bin/python -m pip freeze | grep Django
Django==1.11.27

Untuk mengatur ulang tox env yang digunakan untuk pengujian dengan versi Django yang berbeda ke tox toks biasa, jalankan perintah `` tox`` dengan `` -r`` untuk membuatnya kembali.

$ tox -e py36 -r

Laporan liputan

Mungkin saja tes gagal pada patch Anda karena npm-run-test tidak melewati ambang minimum. Ini tidak selalu terkait langsung dengan fungsi-fungsi dalam patch yang gagal, tetapi lebih dari itu tidak ada cukup tes lintas horizon yang terkait dengan patch Anda.

Laporan liputan dapat ditemukan di direktori 'cover'. Ada subdirektori untuk horizon dan openstack_dashboard, dan kemudian di bawah direktori untuk browser yang digunakan untuk menjalankan tes Anda harus menemukan index.html. Ini kemudian dapat dilihat untuk melihat detail liputan.

Dalam skenario ini, Anda mungkin perlu mengirimkan patch sekunder untuk mengatasi cakupan tes untuk fungsi lain dalam horizon untuk memastikan tes naik di atas ambang batas cakupan dan patch asli Anda dapat lulus tes yang diperlukan.

Perangkap umum

Ada sejumlah cara khas (dan non-obvious) untuk memecahkan tes unit. Beberapa hal umum yang harus dicari:

  1. Pastikan Anda mematikan metode persis seperti yang disebut dalam kode yang sedang diuji. Misalnya, jika kode asli Anda memanggil api.keystone.tenant_get, mematikan api.tenant_get (tersedia untuk legacy reason) akan gagal.

  2. Ketika mendefinisikan input yang diharapkan untuk panggilan yang terhenti, pastikan argumennya identical, ini termasuk perbedaan str vs int.

  3. Pastikan data pengujian Anda sepenuhnya sejalan dengan input yang diharapkan. Sekali lagi, str vs. int atau properti yang hilang pada objek uji akan mematikan pengujian Anda.

  4. Pastikan tidak ada yang salah dalam template Anda (terutama tag {% url %} dan argumennya). Ini sering muncul ketika refactoring tampilan atau mengubah nama variabel konteks. Ini dapat dengan mudah menghasilkan kesalahan yang mungkin tidak Anda temui saat mengklik di sekitar server pengembangan.

  5. Pastikan Anda tidak mengarahkan ulang ke tampilan yang tidak ada lagi, misal tampilan index untuk panel yang digabungkan (seperti instance & volume).

  6. Pastikan Anda mengulangi semua panggilan metode yang terhenti yang terjadi lebih dari sekali. Mereka tidak secara otomatis mengulang, Anda harus mendefinisikannya secara eksplisit. Meskipun ini merepotkan, ini membuat Anda benar-benar sadar berapa banyak panggilan API yang terlibat dalam fungsi tertentu.