%100 Coverage Peşinde İşlevsiz Test Yazmak
Test coverage bir hedef değil, bir yan üründür. Sayıyı yükseltmek için yazılan, hiçbir hatayı yakalamayan testlerin maliyeti.
Kısaca
Coverage yalnızca satırın çalıştığını ölçer, doğrulandığını değil; hedefe dönüştüğünde sayıyı en ucuz yoldan yükselten, hiçbir hatayı yakalamayan testler yazılır. Testin değeri yakaladığı hatadadır: önemli davranışı test edin, coverage yan ürün olarak gelsin. Test bütçesini karmaşık mantığa, para işleyen koda ve daha önce hata çıkmış yerlere harcayın.
Bir pull request gördüm: kırk yeni test, hepsi tek bir amaç içindi — coverage’ı %100’e çıkarmak. Testlerin çoğu bir getter’ı çağırıp, az önce set edilen değerin geri döndüğünü doğruluyordu. Coverage yeşile döndü. O kırk testin yakalayacağı hata sayısı: sıfır.
Test coverage yararlı bir sayıdır — bir hedefe dönüştürülene kadar.
Coverage neyi ölçer, neyi ölçmez
Coverage tek bir şeyi ölçer: testler çalışırken kodun hangi satırlarının çalıştığını. Ölçmediği şey çok daha önemli: o satırların gerçekten doğrulanıp doğrulanmadığını.
Bir satır, hiçbir anlamlı assert içermeyen bir testle de “kapsanmış” sayılır. Kod çalışır, test yeşildir, ama kodun doğru davranıp davranmadığını kimse kontrol etmemiştir. Coverage, çalışan kod ile doğrulanan kod arasındaki farkı göremez.
Yanlış metrik yanlış testi teşvik eder
Coverage bir hedef hâline geldiğinde insan davranışı tahmin edilebilir: sayıyı en ucuz yoldan yükseltecek testler yazılır.
- Getter/setter testleri — mantığı olmayan kodu test etmek.
- Mock’un çağrıldığını doğrulayan testler — gerçek bir sonuç değil, bir etkileşim.
assert’ı anlamsız, sadece “patlamadı” diyen testler.
Bunlar coverage sayısını yükseltir ve hiçbir hatayı yakalamaz. Daha kötüsü: yeşil bir %100, ekibe yanlış bir güven verir. Test edilmiş sanılan kod, aslında sadece çalıştırılmıştır.
İyi testin ölçüsü
Bir testin değeri, kapsadığı satırda değil, yakaladığı hatadadır. Basit bir sınama: kodun mantığını kasten bozun — bir +’yı - yapın, bir koşulu ters çevirin. İyi bir test kırmızıya döner. Dönmüyorsa, o test bir şey doğrulamıyordur.
Bu fikrin sistematik hâli mutation testing’dir: araç kodu küçük yollarla bozar ve testlerinizin bunu yakalayıp yakalamadığını ölçer. Coverage “satır çalıştı mı” der; mutation testing “satır gerçekten test edildi mi” der.
Coverage bir yan üründür
Doğru sıralama tersinedir: önce önemli davranışı test edin, coverage da bir yan ürün olarak yükselsin. Sayıyı kovaladığınızda işlevsiz test yazarsınız; davranışı kovaladığınızda coverage zaten gelir — ve gelen coverage gerçektir.
%100 bir hedef değildir. Hiç test edilmemiş kritik bir yol, %100’lük bir kod tabanında bile olabilir; tersine, %75 coverage’lı bir sistem her riskli yolu sağlam test ediyor olabilir.
Test bütçesini nereye
Test yazmak da kod yazmaktır; sınırlı bir bütçesi vardır. O bütçeyi riske göre harcayın:
- Karmaşık mantık, para işleyen kod, hesaplamalar.
- Edge case’ler — sınır değerler, boş girdi, eşzamanlılık.
- Daha önce bir kez hata çıkmış yerler — hata bir kez oradan çıktıysa, yine çıkar.
Önemsiz, mantıksız kodu test etmek bütçeyi boşa harcar. Gereğinden karmaşık sistem sinyallerinde değindiğim “test kurulumu testin kendisinden uzun” işareti de buraya bağlanır: bir testi yazmak çok zorsa, sorun testte değil, test edilen kodun fazla bağımlı olmasındadır.
Coverage yüzdesi bir güven kaynağı değildir; yalnızca bir gözlemdir. Güveni testlerin yakaladığı hatalar verir — kovaladığı sayı değil.
Sayıyı değil, kod yanlış olduğunda kırmızıya dönecek testi hedefleyin.