Analisis mutasi, atau cara menguji tes

Tidak pernah ada terlalu banyak tes - semua orang tahu itu. Meme tentang unit dan pengujian integrasi tidak lagi menyenangkan. Tetapi kami masih tidak tahu apakah mungkin untuk mengandalkan hasil lulus tes, dan berapa persen cakupan yang memungkinkan kami untuk mencegah bug dalam produksi. Jika perubahan fatal pada kode melewati tes, tanpa mempengaruhi hasilnya, maka solusinya menunjukkan sendiri - Anda perlu menguji tes!



Pendekatan untuk mengotomatisasi tugas ini adalah laporan Mark Langovoy di Frontend Conf . Video dan artikelnya singkat, dan idenya sangat bagus - Anda perlu mencatat.


Tentang pembicara: Mark Langovoi ( marklangovoi ) bekerja di Yandex dalam proyek Yandex.Tolok . Ini adalah platform crowdsourcing untuk secara cepat menandai sejumlah besar data. Pelanggan mengunduh data yang, misalnya, perlu dipersiapkan untuk digunakan dalam algoritma pembelajaran mesin, dan menetapkan harga, dan di sisi lain, pelaksana dapat menyelesaikan tugas dan mendapatkan uang.

Di waktu luangnya, Mark mengembangkan Hari Pengembang Krasnodar Devodar, salah satu dari 19 komunitas TI yang aktivisnya kami undang ke Frontend Conf di Moskow.

Pengujian


Ada berbagai jenis pengujian otomatis.


Selama pengujian unit yang populer , kami menulis tes untuk bagian kecil (modul) aplikasi. Mereka mudah ditulis, tetapi kadang-kadang selama integrasi dengan modul lain, mereka mungkin tidak berperilaku tepat seperti yang kita harapkan.

Untuk menghindari hal ini, kita dapat menulis tes integrasi yang akan menguji operasi modul kita bersama.


Mereka sedikit lebih rumit, jadi hari ini kita akan fokus pada pengujian unit.

Pengujian unit


Setiap proyek yang menginginkan setidaknya stabilitas minimal adalah penulisan unit test.

Pertimbangkan sebuah contoh.

class Signal { on(callback) { ... } off(callback) { const callbackIndex = this.listeners.indexOf(callback); if (callbackIndex === -1) { return; } this.listeners = [ ...this.listeners.slice(0, callbackIndex - 1), ...this.listeners.slice(callbackIndex) ]; } trigger() { ... } } 

Ada kelas Signal - ini adalah Event Emitter, yang memiliki metode on untuk berlangganan dan metode off untuk menghapus langganan - kami memeriksa apakah callback terdapat dalam array pelanggan, lalu hapus. Dan, tentu saja, ada metode pemicu yang akan memanggil panggilan balik yang ditandatangani.

Kami memiliki tes sederhana untuk contoh ini yang memanggil metode on dan off, dan kemudian pemicu, untuk memverifikasi bahwa panggilan balik tidak dipanggil setelah berhenti berlangganan.

 test('off method should remove listener', () => { const signal = new Signal(); let wasCalled = false; const callback = () => { wasCalled = true; }; signal.on(callback); signal.off(callback); signal.trigger(); expect(wasCalled).toBeFalsy(); }); 

Kriteria Penilaian Kualitas


Apa kriteria untuk menilai kualitas tes semacam itu?

Cakupan kode adalah kriteria paling populer dan terkenal yang menunjukkan berapa persen dari baris kode dieksekusi ketika tes dijalankan.


Anda mungkin memiliki 70%, 80%, atau semua cakupan Kode 90%, tetapi apakah ini berarti bahwa ketika Anda mengumpulkan build berikutnya untuk produksi, semuanya akan baik-baik saja, atau ada yang salah?

Mari kita kembali ke contoh kita.

Jumat malam, Anda lelah, Anda sedang menyelesaikan fitur berikutnya. Dan kemudian Anda menemukan kode ini yang ditulis rekan Anda. Sesuatu tentang dirimu tampak rumit dan menakutkan bagimu.

  ...this.listeners.slice(0, callbackIndex - 1), ...this.listeners.slice(callbackIndex) 

Anda memutuskan bahwa Anda mungkin dapat menghapus array:

 class Signal { ... off(callback) { const callbackIndex = this.listeners.indexOf(callback); if (callbackIndex === -1) { return; } this.listeners = []; } ... } 

Saya berkomitmen, menyusun proyek dan mengirimkannya ke produksi. Tes lulus - mengapa tidak? Dan dia pergi beristirahat di bar.



Tetapi tiba-tiba, larut malam, sebuah telepon berdering ke penerima, bahwa semuanya jatuh, orang tidak dapat menggunakan produk, dan secara umum, bisnis membuang-buang uang! Anda terbakar, Anda diancam akan dipecat.



Bagaimana cara menghadapinya? Apa yang harus dilakukan dengan tes? Bagaimana cara menangkap kesalahan bodoh primitif seperti itu? Siapa yang akan menguji tes?

Tentu saja, Anda dapat menyewa pasukan insinyur QA - biarkan mereka duduk dan bertepuk tangan aplikasi kami.



Atau menyewa otomasi QA. Mereka dapat disalahkan pada tes menulis - mengapa menulis sendiri jika ada orang khusus untuk ini?

Tetapi sebenarnya itu mahal, jadi hari ini kita akan berbicara tentang analisis mutasional atau pengujian mutasional.

Pengujian Mutasi


Ini adalah cara untuk mengotomatiskan proses pengujian pengujian kami. Tujuannya adalah untuk mengidentifikasi tes yang tidak efektif dan tidak lengkap, yaitu, pada kenyataannya, ini adalah tes pengujian .

Idenya adalah mengubah potongan kode, menjalankan tes pada mereka, dan jika tes tidak jatuh, maka mereka tidak lengkap.

Perubahan dibuat menggunakan operasi tertentu - mutator . Mereka mengganti, misalnya, ditambah dengan minus, kalikan dengan membagi, dan operasi serupa lainnya. Mutator dapat mengubah potongan kode, mengganti kondisi sementara, nol array bukannya menambahkan beberapa elemen ke array.


Sebagai hasil dari penerapan mutasi ke kode sumber, ia bermutasi dan menjadi mutan .

Mutan dibagi menjadi dua kategori:

  1. Membunuh - orang-orang di mana kami dapat mengidentifikasi penyimpangan, yaitu, di mana setidaknya satu tes jatuh.
  2. Yang selamat adalah orang-orang yang melarikan diri dari kami dan membawa bug untuk diproduksi.

Untuk menilai kualitas, ada metrik MSI (Indikator Skor Mutasi) - persentase mutan yang terbunuh dan selamat. Semakin besar perbedaan antara tes cakupan kode dan MSI, semakin buruk persentase cakupan kode mencerminkan relevansi pengujian kami.

Ini adalah sedikit teori, dan sekarang pertimbangkan bagaimana ini dapat digunakan dalam JavaScript.

Solusi javascript


Hanya ada satu alat pengujian mutasi yang aktif dalam pengembangan JavaScript - Stryker . Nama ini diberikan kepada instrumen untuk menghormati karakter X-man William Stryker - pencipta "Weapon X" dan seorang pejuang dengan semua mutan.



Stryker bukan pelari ujian seperti Karma atau Jest; juga bukan kerangka uji seperti Mocha atau Jasmine. Ini adalah kerangka pengujian mutasi yang melengkapi infrastruktur Anda saat ini.

Sistem plugin


Stryker sangat fleksibel, sepenuhnya dibangun di atas sistem plug-in, yang sebagian besar ditulis oleh pengembang Stryker.


Ada plugin untuk menjalankan tes pada Jest, Karma dan Mocha. Ada integrasi dengan kerangka kerja Mocha (stryker-mocha-framework) Jasmine (stryker-jasmine) dan set mutator siap pakai untuk JavaScript, TypeScript dan bahkan untuk Vue:

  • stryker-javascript-mutator;
  • stryker-typescript;
  • stryker-vue-mutator.

Mutators for React termasuk dalam stryker-javascript-mutator. Selain itu, Anda selalu dapat menulis mutator Anda sendiri.

Jika Anda perlu mengubah kode sebelum menjalankan, Anda bisa menggunakan plugin untuk Webpack, Babel, atau TypeScript.


Ini semua diatur relatif sederhana.

Konfigurasi


Konfigurasi tidak sulit: Anda hanya perlu menentukan di JSON config yang menjalankan test runner (dan / atau kerangka uji dan / atau transpiler) yang Anda gunakan, serta menginstal plugin yang sesuai dari npm.

Stryker-cli utilitas konsol sederhana dapat melakukan semua ini untuk Anda dalam mode tanya jawab. Dia akan bertanya apa yang Anda gunakan, dan akan mengkonfigurasi dirinya sendiri.

Bagaimana cara kerjanya


Siklus hidup sederhana dan terdiri dari langkah-langkah berikut:

  • Membaca dan menganalisis konfigurasi. Stryker mengunduh konfigurasi dan menganalisisnya untuk berbagai plugin, pengaturan, pengecualian file, dll.
  • Unduh plugin sesuai dengan konfigurasi.
  • Menjalankan tes pada kode sumber untuk memeriksa apakah tes relevan sekarang (tiba-tiba mereka sudah rusak).
  • Jika semuanya baik-baik, satu set mutan dihasilkan dari file yang kami ijinkan untuk dimutasi.
  • Menjalankan tes pada mutan.



Di atas adalah contoh memulai Stryker:

  • Stryker memulai;
  • membaca konfigurasi;
  • memuat dependensi yang diperlukan;
  • menemukan file yang akan bermutasi;
  • menjalankan tes pada kode sumber;
  • menciptakan 152 mutan;
  • menjalankan tes dalam 8 utas (dalam hal ini, berdasarkan jumlah inti CPU).

Ini bukan proses cepat, jadi lebih baik melakukannya di beberapa server CI / CD.

Setelah melewati semua tes, Stryker memberikan laporan singkat tentang file-file dengan jumlah mutan yang dibuat, dibunuh dan selamat, serta persentase rasio mutan yang terbunuh terhadap survivor (MSI) dan mutator yang digunakan.

Ini adalah masalah potensial yang tidak diperkirakan dalam pengujian kami.

Untuk meringkas


Pengujian mutasi bermanfaat dan menarik . Ini dapat menemukan masalah pada tahap awal pengujian, dan tanpa partisipasi orang. Ini akan mengurangi waktu untuk validasi permintaan tarik, misalnya, karena fakta bahwa pengembang yang memenuhi syarat tidak perlu menghabiskan waktu untuk validasi permintaan tarik, yang sudah memiliki masalah potensial. Atau simpan produksi jika Anda memutuskan untuk mempersiapkan rilis baru pada Jumat malam.

Stryker adalah alat pengujian mutasi multithreaded fleksibel. Ini aktif berkembang, tetapi sejauh ini lembab, belum mencapai versi utama. Misalnya, selama persiapan laporan ini, para pengembangnya akhirnya memungkinkan dalam plugin untuk Babel untuk menentukan file konfigurasi dan memperbaiki integrasi Jest. Ini adalah proyek OpenSource yang dapat dibantu untuk dikembangkan.

Faq
- Bagaimana cara menguji tes mutasi? Tentunya ada kesalahan juga. Dalam contoh pengujian unit pertama, cakupan adalah 90%. Tampaknya semuanya baik-baik saja, tetapi masih kasus-kasus menyelinap ketika semuanya jatuh dan terbakar. Karena itu, mengapa harus ada perasaan bahwa semuanya baik-baik saja setelah meliput tes mutasi ini?

- Saya tidak mengatakan bahwa pengujian mutasi adalah peluru perak dan itu akan menyembuhkan segalanya. Tentu, mungkin ada beberapa kasus gila batas atau tidak adanya semacam mutator. Pertama-tama, kesalahan tipikal mudah ditangkap. Misalnya, Anda memberi tanda centang pada usia, atur ke <18 (itu perlu <=), dan dalam tes lupa melakukan pemeriksaan kasus batas. Anda membuat perbandingan lain dengan mutator, dan sebagai hasilnya, tes jatuh (atau tidak jatuh), dan Anda mengerti bahwa semuanya baik atau semuanya buruk. Hal-hal seperti itu cepat ditangkap. Ini adalah cara untuk hanya menambahkan tes dengan benar, menemukan poin yang hilang.

- Seringkali Anda memiliki situasi "tertegun dan pergi"? Saya pikir ini tidak benar.

- Tidak, tapi saya pikir dalam banyak proyek hal seperti itu memang ada. Secara alami, ini tidak benar. Banyak orang berpikir bahwa cakupan Kode membantu memeriksa semuanya, Anda dapat pergi dengan aman dan tidak khawatir - tetapi tidak demikian.

- Saya akan langsung mengatakan apa masalahnya. Kami memiliki banyak semua jenis reduksi dan hal-hal lain yang kami uji bersama, dan ada banyak dari mereka. Ini semua tumbuh, dan ternyata untuk setiap permintaan tarik, pengujian mutasi diluncurkan, yang membutuhkan banyak waktu. Apakah mungkin menjalankan hanya pada apa yang telah berubah?

"Aku pikir kamu bisa mengkonfigurasinya sendiri." Misalnya, di sisi pengembang, ketika dia mendorong, melakukan, Anda dapat membuat plugin bertahap yang hanya akan menjalankan file yang telah berubah. Pada CI / CD, ini juga mungkin. Dalam kasus kami, proyek ini sangat besar dan tua, dan kami berlatih pengujian spot. Kami tidak memeriksa semuanya, karena itu akan memakan waktu seminggu, akan ada ratusan ribu mutasi. Saya akan merekomendasikan melakukan pemeriksaan langsung, atau mengatur sendiri proses startup selektif. Saya belum melihat alat yang siap pakai untuk integrasi seperti itu.

- Apakah kelengkapan semua kemungkinan mutasi untuk bagian kode tertentu dipastikan? Jika tidak, bagaimana sebenarnya mutasi dipilih?

- Saya pribadi tidak memeriksa, tetapi saya juga tidak menemui masalah dengan ini. Stryker harus menghasilkan semua mutasi yang mungkin pada potongan kode yang sama.

- Saya ingin bertanya tentang snapshot. Tes unit saya menguji logika, dan, termasuk tata letak komponen reaksi snapshot. Secara alami, jika saya mengubah desain logis apa pun, tata letak saya akan berubah di sana. Ini perilaku yang diharapkan, bukan?

- Ya, itulah artinya, bahwa Anda memperbarui foto secara manual.

- Jadi, Anda entah bagaimana mengabaikan foto dalam laporan ini?

- Kemungkinan besar, snapshot perlu diperbarui terlebih dahulu, dan kemudian jalankan pengujian mutasi, jika tidak akan ada banyak sampah dari Stryker.

- Pertanyaan tentang server CI. Untuk pengujian unit sederhana, ada reporter, di bawah GitLab, untuk apa pun yang Anda inginkan, yang menampilkan persentase tes yang berhasil, dan Anda dapat mengonfigurasi apakah gagal atau tidak gagal. Bagaimana dengan Stryker? Ini hanya menampilkan tablet di konsol, tetapi apa yang bisa saya lakukan selanjutnya?

- Mereka memiliki HTML-reporter, Anda dapat membuat reporter Anda sendiri - semuanya dapat disesuaikan secara fleksibel. Mungkin ada beberapa alat khusus, tetapi karena kami masih melakukan pengujian mutasi titik, saya tidak menemukan integrasi spesifik dengan TeamCity dan alat CI / CD serupa.

- Seberapa banyak tes mutasi meningkatkan dukungan untuk tes yang Anda miliki secara umum? Artinya, tes itu menyusahkan, dan tes harus ditulis ulang ketika kode ditulis ulang, dll. Terkadang lebih mudah untuk menulis ulang kode daripada tes. Dan di sini saya juga memiliki tes mutasi. Seberapa mahal untuk sebuah bisnis?

- Pertama, saya mungkin akan memperbaiki bahwa menulis ulang kode demi tes itu salah. Kode harus mudah diuji. Mengenai apa yang perlu diselesaikan, penting sekali bagi bisnis ini agar pengujiannya selengkap dan seefektif mungkin. Jika tidak lengkap, ini berarti bug dapat terjadi yang akan menyebabkan kerugian. Secara alami, Anda hanya dapat menguji bagian terpenting untuk bisnis.

"Tetap saja, betapa jauh lebih mahal jadinya ketika tes mutasi muncul, daripada jika mereka tidak ada di sana."

- Sebanyak tes buruk sekarang. Jika tes ditulis dengan buruk sekarang, Anda harus menambahkan banyak. Pengujian mutasi akan menemukan kasus yang tidak tercakup oleh tes.

“Ada banyak penilaian di slide hasil tes Stryker, mereka kritis atau tidak kritis. Bagaimana cara menangani kesalahan positif?

- Pertanyaan halus adalah apa yang dianggap salah. Saya bertanya kepada orang-orang di tim kami hal-hal menarik apa yang terjadi pada mereka. Ada contoh tentang teks kesalahan. Stryker melaporkan bahwa tes tidak menanggapi perubahan teks kesalahan. Tampaknya menjadi tiang, tetapi kecil.

- Jadi Anda melihat kesalahan seperti itu dan melewatkan kesalahan yang tidak penting dalam mode manual?

"Kami memiliki pemeriksaan spot, jadi ya."

- Saya punya pertanyaan praktis. Ketika Anda menerapkan ini, berapa persen dari tes yang Anda gagal?

- Kami tidak mengimplementasikannya pada keseluruhan proyek, tetapi ada masalah kecil pada proyek baru. Oleh karena itu, saya tidak bisa mengatakan angka pastinya, tetapi secara umum, pendekatannya sudah pasti memperbaiki situasi.

Lihat pertunjukan front-end lainnya yang sama bermanfaatnya di saluran youtube kami, semua laporan tematik dari semua konferensi kami secara bertahap sampai di sana. Atau berlangganan buletin , dan kami akan memberi Anda informasi tentang semua materi baru dan berita konferensi mendatang.

Source: https://habr.com/ru/post/id421141/


All Articles