Pengenalan kepada Ujian Mutasi

Ujian Mutasi (dalam bahasa Perancis: tests de mutation), saya baru-baru ini menemui istilah ini yang menerangkan proses yang mampu mengesan jurang dalam ujian unit, melangkaui liputan kod. Hari ini, saya membentangkan kepada anda pendekatan ini yang terdiri daripada menjalankan ujian ini dengan mengendalikan kod.

Ujian unit

Memandangkan kegunaan ujian unit sudah mantap, subjek ini menjadi menarik jika anda sedang membangunkan projek yang diuji, tidak kira betapa pentingnya liputan kod.
Ujian unit membenarkan penonjolan regresi yang mungkin disebabkan oleh pengubahsuaian kod. Secara teori, jika ujian mengesahkan program, ini bermakna semuanya berfungsi dengan betul dalam aplikasi. Sebagai yang pertama dan selalunya satu-satunya ukuran kepercayaan, kami menggunakan liputan kod. Semakin hampir metrik ini menjadi 100%, semakin ia meyakinkan kita bahawa tiada regresi akan tergelincir melalui celah-celahnya. Malangnya, pernyataan ini kekal sebagai teori.
Ujian, walaupun penting untuk pengesahan aplikasi kualitatif, sukar untuk ditunjukkan atau bahkan untuk menghargai kaitannya.

Liputan kod dan liputan kes

Liputan kod 100% tidak bermakna kod disahkan 100% tetapi hanya 100% kod ini dilaksanakan apabila lulus ujian, tidak lebih.
Liputan kod (baris, penyata, cawangan, dsb.) hanya mengukur kod yang telah dilaksanakan oleh ujian, tanpa jaminan pengesanan kecacatan. Ia hanya dapat mengenal pasti kod yang masih belum diuji.
Pengujian tanpa penegasan adalah contoh yang jelas kerana, walaupun dilaksanakan, kod itu sebenarnya tidak diuji. Nasib baik, senario ini kekal jarang berlaku, yang paling biasa ialah menemui kod yang sebahagiannya diuji oleh suite ujian. Suite yang hanya menguji sebahagian kod yang masih boleh menjalankan semua cawangannya.
Dalam sesetengah kes, liputan kod bukan penunjuk perlindungan. Berikut adalah contoh mudah:

function isAdult(user) {
    return user.age >= 18;
}

Katakan kita ingin menyemak umur pengguna. Kami akan menulis kod berikut untuk memastikan ia adalah major.
Untuk menguji kod ini kita boleh mencuba dengan 12 dan 38 sebagai input. Tindakan ini sudah memadai untuk menampung kod ini 100%.
Hasilnya adalah sama jika kami tidak menganggap 18 sebagai majoriti dengan kesilapan menaip ini dalam kod kami:

function isAdult(user) {
    return user.age > 18;
}

…atau jika kami hanya menguji nilai 12 tahun, atau lebih teruk lagi jika kami meninggalkan penegasan dalam ujian kami.
Ujian mutasi sebenarnya akan dapat mengesan jika setiap pernyataan diuji dengan bermakna. Ia adalah ukuran standard untuk semua jenis perlindungan lain.

Isu lain dalam kod

Mari kita anggap bahawa kita tidak mahu kod yang tidak diperlukan dalam aplikasi kita. Sesungguhnya, setiap bahagian yang belum diuji akan menjadi sumber pepijat yang berpotensi atau kerumitan tambahan jika ia tidak penting.
Inilah sebabnya ujian mutasi ialah cara terbaik untuk menguji kaitan kod tersebut:
jika (someVariable !== null && someVariable.hasValue()) {}
Adakah kita perlu menyemak nilai "sifar"? Adakah syarat itu ditambah kerana kebiasaan? Ini mungkin bermakna kita tidak pasti dengan pembolehubah itu”beberapa berubah” dan akan menjamin analisis lanjut. Kita tidak boleh pergi lebih dalam tanpa kita sedari. Ujian mutasi juga membantu kita dengan ini.

Ujian Mutasi: Apakah itu?

Untuk mengesan kecacatan dalam ujian unit kami, terdapat penyelesaian: ujian mutasi.

Teknik ini memberikan lebih keyakinan dalam ujian kami. Ujian mutasi adalah konsep yang agak mudah. Prinsipnya adalah untuk menganiaya kod sumber dengan mengubahnya untuk mengesahkan bahawa ujian yang berkaitan gagal dengan sewajarnya. Kelemahan (atau mutasi) disemai secara automatik ke dalam kod kami, dan kemudian ujian dijalankan. Jika ujian gagal, maka mutasi terbunuh. Sekiranya ujian lulus, maka mutasi itu terselamat. Dalam kes ini, ini bermakna bahawa ujian tidak sepadan dengan kerumitan kod dan meninggalkan satu atau lebih aspeknya tidak diuji. Kemudian, kualiti ujian kami boleh diukur daripada peratusan mutasi yang terbunuh.
Dalam erti kata lain, kami menjalankan ujian unit pada versi kod yang diubah suai secara automatik. Apabila kod aplikasi berubah, ia sepatutnya menghasilkan keputusan yang berbeza dan menyebabkan ujian unit gagal. Jika ujian unit tidak gagal dalam situasi ini, ia mungkin menunjukkan kegagalan dalam suite ujian.
Berikut adalah langkah-langkah untuk mencapainya:

  • Jalankan suite ujian biasa untuk mengesahkan bahawa semua ujian lulus hijau.
  • Ubah suai beberapa bahagian kod yang diuji sebelum menjalankan suite ujian sekali lagi.
  • Pastikan ujian gagal seperti yang diharapkan selepas mengubah suai (memutasi) kod yang diuji.

Ulangi langkah 2 dan 3 selagi mutasi mungkin kekal.
Mari kita ambil contoh konkrit: anggap mutan sebagai kelas tambahan dengan hanya satu perubahan daripada kod asal. Ini boleh menjadi perubahan pengendali logik dalam klausa if seperti yang ditunjukkan di bawah:
if( a || b ) {…} => if( a && b ) {…}
Pengesanan dan penolakan pengubahsuaian sedemikian oleh ujian sedia ada dirujuk sebagai membunuh mutan. Dengan set ujian yang sempurna, tiada mutan kelas akan bertahan. Tetapi mencipta semua kemungkinan mutan memerlukan sumber yang intensif, itulah sebabnya pendekatan ini tidak mungkin dicapai secara manual dalam senario sebenar.
Nasib baik, terdapat alat yang tersedia untuk mencipta mutan dengan cepat dan secara automatik menjalankan semua ujian untuk setiap satu. Penciptaan transformasi adalah berdasarkan satu set pengendali mutasi yang dipanggil untuk mendedahkan ralat pengaturcaraan biasa. Operator mutasi yang digunakan untuk mengubah suai kod di atas dipanggil operator keadaan.

Dalam amalan

Oleh itu teknik ini terdiri daripada dua bahagian: penjanaan mutan, kemudian penyingkiran ini.
Penjanaan mutan ialah langkah menjana kelas mutan daripada kelas sumber. Untuk bermula, kami memerlukan kod perniagaan yang kami mahu menilai perkaitan ujian kami. Kami kemudian mengambil a kolam kemungkinan mutasi, mutasi ialah pengubahsuaian kod sumber, seperti tindakan menggantikan satu operator dengan yang lain.
Berikut adalah beberapa contoh:

  • + menjadi -
  • * MENJADI /
  • >= menjadi ==
  • benar menjadi palsu.
  • memadam arahan
  • dan lain-lain.

Kita boleh mengubah suai ungkapan aritmetik e kepada |e| (ABS), tukar satu operator aritmetik hubungan kepada yang lain (ROR), tukar satu operator aritmetik kepada yang lain (AOR), tukar satu operator boolean kepada yang lain (COR), tukar ungkapan bool/aritmetik dengan menambah − atau ¬ ( UOI), ubah suai nama pembolehubah dengan yang lain, ubah suai nama pembolehubah dengan pemalar jenis yang sama, ubah suai pemalar dengan pemalar lain daripada jenis yang sama…
Penjanaan sebenar terdiri daripada meneliti semua arahan kod dan untuk setiap satu, menentukan sama ada mutasi boleh digunakan. Jika ya, setiap mutasi akan menimbulkan mutan baru.
Untuk pernyataan berikut:

if (a > 8) { x = y+1 }

Kita boleh mempertimbangkan mutan berikut:

 if (a < 8) { x = y+1 }
 if (a ≥ 8) { x = y+1 }
 if (a > 8) { x = y-1 }
 if (a > 8) { x = y }

Proses ini boleh menjadi intensif sumber dengan cepat. Apabila kod yang hendak dimutasi mengandungi sejumlah besar arahan dan " kolam » kemungkinan mutasi adalah ketara, maka bilangan mutan yang dihasilkan meningkat dengan cepat.
Setelah proses penjanaan mutan selesai, mutan disimpan sehingga langkah seterusnya: penghapusan!
Untuk bahagian kedua proses, kami menghasilkan banyak mutan yang kami tidak mahu melalui ujian; matlamatnya adalah untuk menghapuskan sebanyak mungkin. Untuk melakukan ini, senjata kami adalah penambahbaikan ujian unit.

kunci kira-kira

Untuk mutan tertentu, terdapat dua kemungkinan hasil, sama ada ujian sentiasa hijau, atau sekurang-kurangnya satu daripadanya telah bertukar menjadi merah.

Biasanya kita mahu ujian menjadi hijau. Tetapi dalam konteks ini, kami mencari merah. Sesungguhnya, seperti yang kita lihat sebelum ini, setiap mutan sepatutnya gagal sekurang-kurangnya satu daripada ujian unit. Jika sekurang-kurangnya satu daripada ujian gagal, ini membuktikan bahawa mereka dapat mengesan pengubahsuaian kod dan oleh itu menghalang kemungkinan pepijat. Sebaliknya, jika semua ujian kekal hijau, mutan itu bertahan, jadi ia kekal tidak dapat dilihat oleh mata ujian kami.
Oleh itu, mutan yang masih hidup adalah tanda ujian yang hilang!

Batasan

Analisis lengkap kod kami boleh membosankan. Seperti yang telah kita lihat, bilangan mutan boleh meningkat dengan cepat.
Pada fasa pertama, kita boleh menjana 6000 mutan sebagai contoh. Semasa fasa ujian kedua, lebih daripada 98% daripadanya akan dihapuskan, peratusannya berbeza-beza mengikut kualiti ujian anda yang terdahulu. Kami masih mempunyai 150 hingga 200 mutan yang tinggal.
Analisis manual bagi setiap daripada mereka memakan masa. Selain itu, ujian unit kami tidak bertanggungjawab sepenuhnya untuk kelangsungan hidup mereka. Mungkin terdapat "mutan yang setara": mutan yang mengubah suai sintaks kod sumber, tanpa mengubah semantiknya. Mutan jenis ini menghalang ujian unit daripada mengesannya.

while(...) {
    index++;
    if (index == 10)
    break;
}

Sebagai contoh, mutasi " == »Untuk« <= akan menghasilkan mutan yang setara. Contoh ini akan mempunyai keadaan keluar yang sama bagi gelung.
Pra-analisis liputan kod, penciptaan mutan dengan cepat dan semua ujian yang diperlukan memakan banyak masa. Sebagai contoh, kod dengan 350 ujian meningkatkan masa pelaksanaan sebanyak empat berbanding dengan larian biasa.
Memandangkan nombor ini dan atas sebab praktikal, ujian mutasi tidak boleh dijalankan sekerap ujian unit. Oleh itu, adalah penting untuk mencari aliran kerja yang sesuai yang menawarkan kompromi terbaik dari segi kecekapan. Untuk sistem perisian yang besar, ini mungkin bermakna ujian mutasi akan dihadkan kepada larian setiap malam.
Sebelum melaksanakannya, anda mesti berada dalam pendekatan kualiti lanjutan. Ujian mesti diletakkan di tengah-tengah pembangunan, untuk mengelakkan keputusan yang terlalu besar untuk dianalisis. Walau bagaimanapun, jika liputan kod telah mencapai hadnya, ini mungkin pendekatan yang baik untuk bereksperimen. Malangnya, alat semasa nampaknya tidak cukup berindustri.

Ujian mutasi dan javascript

Ujian mutasi jauh lebih dikenali dan digunakan dalam dunia Java atau dalam PHP. Walau bagaimanapun, sejak 2016 terdapat cara untuk melakukan ujian mutasi dalam JavaScript terima kasih kepada Stryker Mutator. Terdapat juga ujian-mutasi Grunt, majoriti kod sumbernya sedang dalam proses dipindahkan ke Stryker.
Berikut ialah pautan ke Github: http://stryker-mutator.github.io

Kesimpulan

Artikel ini adalah pengenalan pantas kepada ujian mutasi. Kami menangani mutan ujian, menghargai hubungan langsung antara kadar mutan dan kualiti suite ujian sedia ada, dan memerhatikan korelasi dengan liputan kod.
Memandangkan liputan kod bukanlah metrik yang boleh dipercayai, Ujian mutasi ialah cara yang cepat dan mudah untuk mengukur kebolehpercayaan ujian unit. Kami akan mempromosikan ujian mutasi jika terdapat isu sebenar: kod perniagaan.
Secara keseluruhannya, ujian mutasi kelihatan seperti tambahan yang bagus kepada set alat jaminan kualiti., berdasarkan ujian automatik. Amalan ini agak baru dalam JavaScript dan masih tidak diketahui. Ia akan menjadi menarik untuk membaca pendapat dan maklum balas daripada pengguna lanjutan.
Aurélie Ambal, (@Souvir) JS Craftswoman @JS-Republic
[warna kotak tindakan=”default” title=”” description=”Latihan JS-REPUBLIK dirujuk oleh Datadock.
Dapatkan semua kursus latihan kami di laman web kami training.ux-republic.com:

  • Reka Bentuk UX
  • Agile
  • JavaScript

” btn_label=”Latihan kami” btn_link=”http://training.ux-republic.com” btn_color=”primary” btn_size=”big” btn_icon=”star” btn_external=”1″]