Pengujian Mutasi dengan PITest

1. Ikhtisar

Pengujian perangkat lunak mengacu pada teknik yang digunakan untuk menilai fungsionalitas aplikasi perangkat lunak. Pada artikel ini, kita akan membahas beberapa metrik yang digunakan dalam industri pengujian perangkat lunak, seperti cakupan kode dan pengujian mutasi , dengan minat khusus tentang cara melakukan uji mutasi menggunakan pustaka PITest .

Demi kesederhanaan, kita akan mendasarkan demonstrasi ini pada fungsi palindrome dasar - Perhatikan bahwa palindrome adalah string yang membaca maju dan mundur yang sama.

2. Ketergantungan Maven

Seperti yang Anda lihat di konfigurasi dependensi Maven, kita akan menggunakan JUnit untuk menjalankan pengujian dan library PITest untuk memasukkan mutan ke dalam kode kita - jangan khawatir, kita akan segera melihat apa itu mutan. Anda selalu dapat mencari versi dependensi terbaru terhadap repositori pusat maven dengan mengikuti tautan ini.

 org.pitest pitest-parent 1.1.10 pom  

Agar pustaka PITest aktif dan berjalan, kita juga perlu menyertakan plugin pitest-maven di file konfigurasi pom.xml kita :

 org.pitest pitest-maven 1.1.10   com.baeldung.testing.mutation.*   com.baeldung.mutation.test.*    

3. Pengaturan Proyek

Sekarang setelah kita mengonfigurasi dependensi Maven, mari kita lihat fungsi palindrome yang dapat menjelaskan sendiri ini:

public boolean isPalindrome(String inputString) { if (inputString.length() == 0) { return true; } else { char firstChar = inputString.charAt(0); char lastChar = inputString.charAt(inputString.length() - 1); String mid = inputString.substring(1, inputString.length() - 1); return (firstChar == lastChar) && isPalindrome(mid); } } 

Yang kita butuhkan sekarang adalah pengujian JUnit sederhana untuk memastikan bahwa implementasi kita bekerja dengan cara yang diinginkan:

@Test public void whenPalindrom_thenAccept() { Palindrome palindromeTester = new Palindrome(); assertTrue(palindromeTester.isPalindrome("noon")); } 

Sejauh ini bagus, kami siap menjalankan kasus pengujian kami dengan sukses sebagai pengujian JUnit.

Selanjutnya, pada artikel ini, kita akan fokus pada cakupan kode dan mutasi menggunakan pustaka PITest.

4. Cakupan Kode

Cakupan kode telah digunakan secara luas dalam industri perangkat lunak, untuk mengukur berapa persen dari jalur eksekusi yang telah dilakukan selama pengujian otomatis.

Kami dapat mengukur cakupan kode yang efektif berdasarkan jalur eksekusi menggunakan alat seperti Eclemma yang tersedia di Eclipse IDE.

Setelah menjalankan TestPalindrome dengan cakupan kode, kita dapat dengan mudah mencapai skor cakupan 100% - Perhatikan bahwa isPalindrome bersifat rekursif, jadi cukup jelas bahwa pemeriksaan panjang masukan yang kosong akan tetap tercakup.

Sayangnya, metrik cakupan kode terkadang bisa sangat tidak efektif , karena skor cakupan kode 100% hanya berarti bahwa semua baris dijalankan setidaknya satu kali, tetapi tidak menjelaskan apa pun tentang akurasi pengujian atau kelengkapan kasus penggunaan , dan itulah mengapa pengujian mutasi sebenarnya penting.

5. Cakupan Mutasi

Pengujian mutasi adalah teknik pengujian yang digunakan untuk meningkatkan kecukupan pengujian dan mengidentifikasi cacat dalam kode. Idenya adalah mengubah kode produksi secara dinamis dan menyebabkan pengujian gagal.

Tes yang baik akan gagal

Setiap perubahan dalam kode disebut mutan , dan menghasilkan versi program yang diubah, yang disebut mutasi .

Kami mengatakan bahwa mutasi dimatikan jika dapat menyebabkan kegagalan dalam pengujian. Kami juga mengatakan bahwa mutasi bertahan jika mutan tidak dapat mempengaruhi perilaku tes.

Sekarang mari kita jalankan pengujian menggunakan Maven, dengan opsi tujuan ditetapkan ke: org.pitest: pitest-maven: mutationCoverage .

Kami dapat memeriksa laporan dalam format HTML di direktori target / pit-test / YYYYMMDDHHMI :

  • Cakupan garis 100%: 7/7
  • 63% cakupan mutasi: 5/8

Jelas, pengujian kami menyapu semua jalur eksekusi, dengan demikian, skor cakupan garis adalah 100%. Di sisi lain, perpustakaan PITest memperkenalkan 8 mutan , 5 di antaranya terbunuh - Disebabkan gagal - tetapi 3 selamat.

Kita dapat memeriksa laporan com.baeldung.testing.mutation / Palindrome.java.html untuk lebih jelasnya tentang mutan yang dibuat:



Ini adalah mutator yang aktif secara default saat menjalankan uji cakupan mutasi:

  • INCREMENTS_MUTATOR
  • VOID_METHOD_CALL_MUTATOR
  • RETURN_VALS_MUTATOR
  • MATH_MUTATOR
  • NEGATE_CONDITIONALS_MUTATOR
  • INVERT_NEGS_MUTATOR
  • CONDITIONALS_BOUNDARY_MUTATOR

Untuk lebih jelasnya tentang mutator PITest, kamu bisa cek di link halaman dokumentasi resmi .

Skor cakupan mutasi kami mencerminkan kurangnya kasus uji , karena kami tidak dapat memastikan bahwa fungsi palindrom kami menolak input string non-palindromik dan dekat-palindromik.

6. Meningkatkan Skor Mutasi

Sekarang kita tahu apa itu mutasi, kita perlu meningkatkan skor mutasi kita dengan membunuh mutan yang masih hidup .

Mari kita ambil mutasi pertama - negated conditional - pada baris 6 sebagai contoh. Mutan bertahan karena meskipun kita mengubah cuplikan kode:

if (inputString.length() == 0) { return true; }

Untuk:

if (inputString.length() != 0) { return true; }

Ujian akan lulus, dan itulah mengapa mutasi bertahan . Idenya adalah untuk mengimplementasikan pengujian baru yang akan gagal, jika mutan diperkenalkan . Hal yang sama bisa dilakukan untuk mutan yang tersisa.

@Test public void whenNotPalindrom_thanReject() { Palindrome palindromeTester = new Palindrome(); assertFalse(palindromeTester.isPalindrome("box")); } @Test public void whenNearPalindrom_thanReject() { Palindrome palindromeTester = new Palindrome(); assertFalse(palindromeTester.isPalindrome("neon")); }

Sekarang kami dapat menjalankan pengujian kami menggunakan plugin cakupan mutasi, untuk memastikan bahwa semua mutasi telah dimatikan , seperti yang dapat kami lihat di laporan PITest yang dibuat di direktori target.

  • Cakupan garis 100%: 7/7
  • 100% cakupan mutasi: 8/8

7. Konfigurasi Tes PITest

Mutation testing may be resources-extensive sometimes, so we need to put proper configuration in place to improve tests effectiveness. We can make use of the targetClasses tag, to define the list of classes to be mutated. Mutation testing cannot be applied to all classes in a real world project, as it will be time-consuming, and resource critical.

It is also important to define the mutators you plan to use during mutation testing, in order to minimize the computing resources needed to perform the tests:

  com.baeldung.testing.mutation.*   com.baeldung.mutation.test.*   CONSTRUCTOR_CALLS VOID_METHOD_CALLS RETURN_VALS NON_VOID_METHOD_CALLS  

Moreover, the PITest library offers a variety of options available to customize your testing strategies, you can specify the maximum number of mutants introduced by class using the maxMutationsPerClass option for example. More details about PITest options in the official Maven quickstart guide.

8. Conclusion

Note that code coverage is still an important metric, but sometimes it is not sufficient enough to guarantee a well-tested code. So in this article we've walked through mutation testing as a more sophisticated way to ensure tests quality and endorse test cases, using the PITest library.

Kami juga telah melihat bagaimana menganalisis laporan PITest dasar sambil meningkatkan skor cakupan mutasi .

Meskipun pengujian mutasi menunjukkan adanya cacat pada kode, pengujian tersebut harus digunakan dengan bijak, karena ini adalah proses yang sangat mahal dan memakan waktu .

Anda dapat melihat contoh yang diberikan dalam artikel ini di proyek GitHub yang ditautkan .