Belajar mutmut - alat pengujian mutasi Python

Pengujian mutasi memungkinkan Anda mengidentifikasi bug yang tidak tercakup dalam pengujian konvensional.



Apakah Anda memiliki tes untuk semua kesempatan? Atau mungkin repositori proyek Anda berisi bantuan "Tentang Cakupan Tes 100%"? Tetapi apakah semuanya begitu sederhana dan dapat dicapai dalam kehidupan nyata?







Dengan tes unit, semuanya menjadi lebih atau kurang jelas: mereka harus ditulis. Terkadang mereka tidak berfungsi seperti yang diharapkan: ada positif palsu atau tes dengan kesalahan yang akan menghasilkan ya dan tidak tanpa perubahan kode apa pun. Bug kecil yang dapat Anda temukan dalam pengujian unit sangat berharga, tetapi sering kali diperbaiki oleh pengembang sendiri - sebelum dia melakukannya. Tapi kami sangat khawatir dengan kesalahan-kesalahan yang sering luput dari pandangan. Dan yang terburuk dari semuanya, mereka sering memutuskan untuk membuat nama untuk diri mereka sendiri tepat ketika produk jatuh ke tangan pengguna.



Ini adalah pengujian mutasimemungkinkan Anda menangani bug berbahaya tersebut. Ini memodifikasi kode sumber dengan cara yang telah ditentukan (memperkenalkan bug khusus - yang disebut "mutan") dan memeriksa apakah mutan ini bertahan dalam pengujian lain. Setiap mutan yang selamat dari tes unit mengarah pada kesimpulan bahwa tes standar tidak menemukan potongan kode yang dimodifikasi yang mengandung kesalahan.



Di Python, mutmut adalah alat utama untuk pengujian mutasi .



Bayangkan kita perlu menulis kode yang menghitung sudut antara jarum jam dan menit dalam jam analog:



def hours_hand(hour, minutes):
    base = (hour % 12 ) * (360 // 12)
    correction = int((minutes / 60) * (360 // 12))
    return base + correction

def minutes_hand(hour, minutes):
    return minutes * (360 // 60)

def between(hour, minutes):
    return abs(hours_hand(hour, minutes) - minutes_hand(hour, minutes))


Mari tulis pengujian unit dasar:



import angle

def test_twelve():
    assert angle.between(12, 00) == 0


Tidak ada kata " jika" dalam kode . Mari kita periksa sejauh mana pengujian unit tersebut mencakup semua kemungkinan situasi:



$ coverage run `which pytest`
============================= test session starts ==============================
platform linux -- Python 3.8.3, pytest-5.4.3, py-1.8.2, pluggy-0.13.1
rootdir: /home/moshez/src/mut-mut-test
collected 1 item                                                              

tests/test_angle.py .                                                    [100%]

============================== 1 passed in 0.01s ===============================


Luar biasa! Seperti cakupan 100%. Tetapi apa yang terjadi jika kita melakukan pengujian mutasi?







Oh tidak! Dari 21, sebanyak 16 mutan selamat. Bagaimana?



Untuk setiap uji mutasi, sebagian dari kode sumber perlu dimodifikasi yang mensimulasikan potensi kesalahan. Contoh modifikasi seperti itu adalah mengubah operator perbandingan ">" menjadi "> =". Jika tidak ada pengujian unit untuk kondisi batas ini, bug mutan ini akan bertahan: ini adalah bug potensial yang tidak akan dideteksi oleh pengujian biasa.



Baik. Semua jelas. Kita perlu menulis tes unit yang lebih baik. Kemudian, dengan menggunakan perintah hasil, mari kita lihat perubahan spesifik apa yang dibuat:



$ mutmut results
<snip>
Survived :( (16)

---- angle.py (16) ----

4-7, 9-14, 16-21
$ mutmut apply 4
$ git diff
diff --git a/angle.py b/angle.py
index b5dca41..3939353 100644
--- a/angle.py
+++ b/angle.py
@@ -1,6 +1,6 @@
 def hours_hand(hour, minutes):
     hour = hour % 12
-    base = hour * (360 // 12)
+    base = hour / (360 // 12)
     correction = int((minutes / 60) * (360 // 12))
     return base + correction


Ini adalah contoh umum bagaimana mumut bekerja: ia menganalisis kode sumber dan menggantikan beberapa operator dengan yang lain: misalnya, penambahan dengan pengurangan atau, seperti dalam kasus ini, perkalian dengan pembagian. Tes unit, secara umum, harus menangkap kesalahan saat mengubah pernyataan; jika tidak, mereka tidak secara efektif menguji perilaku program. Ini adalah logika yang dianut mutmut saat membuat perubahan tertentu.



Kita bisa menggunakan perintah mutmut apply pada mutan yang masih hidup. Wow, ternyata kami tidak memeriksa apakah parameter jam digunakan dengan benar. Mari perbaiki ini:



$ git diff
diff --git a/tests/test_angle.py b/tests/test_angle.py
index f51d43a..1a2e4df 100644
--- a/tests/test_angle.py
+++ b/tests/test_angle.py
@@ -2,3 +2,6 @@ import angle
 
 def test_twelve():
     assert angle.between(12, 00) == 0
+
+def test_three():
+    assert angle.between(3, 00) == 90


Sebelumnya, kami hanya memeriksa 12. Menambahkan tanda centang untuk nilai 3 akan menghemat hari?







Tes baru ini telah berhasil membunuh dua mutan: ini lebih baik dari sebelumnya, tetapi lebih banyak pekerjaan harus dilakukan. Saya tidak akan menulis solusi untuk masing-masing dari 14 kasus yang tersisa sekarang, karena idenya sudah jelas (dapatkah Anda membunuh semua mutan sendiri?)



Selain mengukur cakupan, pengujian mutasi juga memungkinkan Anda mengevaluasi seberapa komprehensif pengujian Anda. Dengan cara ini Anda dapat meningkatkan pengujian Anda: salah satu mutan yang masih hidup adalah kesalahan yang mungkin dibuat oleh pengembang, serta potensi cacat pada produk Anda. Jadi, saya berharap Anda membunuh lebih banyak mutan!






Periklanan



VDSina menawarkan server virtual di Linux dan Windows - pilih salah satu OS yang sudah diinstal sebelumnya, atau instal dari image Anda.






All Articles