TB
← Tüm yazılar

Coverage metrikleri

Kod kapsama metriklerinin türleri, ölçüm yöntemleri, yanıltıcı yüksek kapsama tuzakları ve anlamlı kapsama hedefleri belirleme stratejilerini ele alıyoruz.

Kod kapsama (code coverage) metrikleri, testlerin kaynak kodun ne kadarını çalıştırdığını sayısal olarak gösterir. Yönetim katmanı %80 hedefi koyar; ekip hızla yeşil rapor üretir ama üretimde hata devam eder. Sorun metrik değil, metriğin yanlış yorumlanmasıdır. Coverage metrikleri test stratejisini yönlendiren sinyal olmalı; amaç değil.

Kapsama türleri

Farklı kapsama türleri farklı sorulara cevap verir. Hangi türün izlendiği rapor okuyucusunun yorumunu doğrudan etkiler.

Satır kapsama (line coverage)

En yaygın ve en anlaşılır metrik. Kaynak dosyadaki yürütülen satır yüzdesini gösterir. Basit ama yanıltıcı: bir satır çalıştırılmış olabilir ama tüm dal koşulları test edilmemiş olabilir.

Dal kapsama (branch coverage)

If/else, switch case, ternary operatör gibi dallanma noktalarının her kolunun en az bir kez çalıştırılma oranıdır. Satır kapsaması %100 iken dal kapsaması %50 olabilir; bu durumda yarım test edilmiş kod vardır.

Fonksiyon kapsama

Tanımlanan fonksiyonların kaçının çağrıldığını ölçer. Dead code tespiti için faydalıdır; ancak fonksiyon çağrılmış olması anlamlı assertion yapıldığı anlamına gelmez.

Koşul kapsama (condition coverage)

Bileşik koşullardaki her alt ifadenin true ve false durumlarını ayrı ayrı test eder. if (a && b) için a tek başına false, b tek başına false ve ikisi birlikte true senaryoları gerekir.

  • Satır: hızlı genel bakış, düşük güven
  • Dal: çoğu ekip için minimum hedef
  • Koşul: karmaşık business logic için gerekli
  • Fonksiyon: API yüzeyi kapsama kontrolü

Ölçüm araçları

.NET ekosisteminde coverlet collector en yaygın seçenektir. Test komutuna --collect:"XPlat Code Coverage" eklenir; Cobertura veya OpenCover formatında rapor üretilir.

dotnet test --collect:"XPlat Code Coverage" \
  --results-directory ./coverage
reportgenerator \
  -reports:./coverage/**/coverage.cobertura.xml \
  -targetdir:./coverage/report \
  -reporttypes:Html

JavaScript/TypeScript tarafında Istanbul (nyc) ve Vitest built-in coverage kullanılır. Python'da coverage.py standarttır. Dil fark etmeksizin raporların CI artefaktı olarak saklanması ve PR'larda diff coverage gösterilmesi kritiktir.

Diff coverage (değişim kapsaması)

Genel proje kapsaması %85 olsa bile yeni PR yalnızca test edilmemiş kod ekleyebilir. Diff coverage, yalnızca değişen satırların kapsama oranını ölçer. PR kapısı olarak %80 diff coverage hedefi, teknik borcun büyümesini engeller.

Diff coverage uygulaması

Git diff ile değişen satırlar çıkarılır; coverage raporu ile kesişim alınır. Codecov, Coveralls ve SonarQube bu hesaplamayı otomatik yapar. Yeni kod test edilmeden merge engellenir; mevcut düşük kapsamalı legacy kod acilen refactor zorunluluğu yaratmaz.

Yanıltıcı yüksek kapsama tuzakları

Assertion içermeyen testler kapsamayı artırır ama davranışı doğrulamaz. Boş test metodu veya yalnızca nesne oluşturan test, satır kapsamasını yükseltir. Mutasyon testi bu sahte güveni ortaya çıkarır.

  1. Assertion'sız test: kod çalışır, hiçbir şey doğrulanmaz
  2. Mock aşırı kullanımı: gerçek dal hiç çalışmaz, kapsama yanıltıcı
  3. Private metod testi: public API kapsaması düşük kalır
  4. Generated code dahil: DTO/mapping dosyaları oranı şişirir
  5. Catch bloğu testi: exception fırlatılıp yakalanır, iş mantığı doğrulanmaz

Anlamlı kapsama hedefleri belirleme

Evrensel %100 hedef gerçekçi değildir. Katman ve risk bazlı hedef belirlenmelidir. Domain logic ve finansal hesaplama modülleri yüksek hedef; UI glue code ve configuration mapping düşük hedef alır.

# coverage-thresholds.yaml
domain:
  line: 90
  branch: 85
application:
  line: 75
  branch: 70
infrastructure:
  line: 60
  branch: 50

Risk bazlı önceliklendirme

Son six ayda en çok bug çıkan modüller coverage raporunda kırmızı işaretlenir. Test yatırımı bu modüllere yoğunlaştırılır. Düşük bug oranı ve yüksek kapsama birlikte değerlendirilir; yüksek kapsama ama yüksek bug oranı test kalitesi sorununa işaret eder.

Kapsama raporunu okuma

HTML raporunda kırmızı satırlar test edilmemiş kodu gösterir. Sarı kısmi dal kapsamasını işaret eder. Rapor okuma oturumu sprint planlamasının parçası olmalıdır: "Bu sprint hangi modülün kapsamasını artırıyoruz?" sorusu backlog'da yer alır.

CI entegrasyonu

Coverage raporu her PR'da otomatik üretilir. Eşik altı kapsama merge engeller. Ancak eşik ani yükseltilmemelidir; ramp-up planı uygulanır: mevcut %55'ten başlayıp çeyrekte %5 artış.

Coverage badge ve şeffaflık

README'deki coverage badge ekibi motive eder ama yanlış teşvik de yaratabilir. Badge yanında dal kapsama ve mutasyon skoru birlikte gösterilmelidir. Tek metrik hikâye anlatmaz.

Exclude stratejisi

Her dosya test edilmeli değildir. Program.cs, migration dosyaları, auto-generated kod ve third-party wrapper'lar exclude listesine alınır. Exclude genişletilmemelidir; kolay yol olarak test edilmesi gereken modül hariç tutulmamalıdır.

[ExcludeFromCodeCoverage]
public class Program { }

Kapsama ve test piramidi ilişkisi

Birim testleri hızlı kapsama artışı sağlar. Entegrasyon testleri repository ve HTTP katmanını kapsar. E2E testleri az sayıda ama kritik user journey'leri kapsar. Piramidin tabanındaki birim testler dal kapsamasını yükseltir; tepe E2E kapsama metriğine minimal katkı yapar ama güven katmanı ekler.

Legacy kod stratejisi

Mevcut projede kapsama %30 ise hedef bir gecede %80'e çekilmez. Strangler fig pattern ile yeni kod yüksek kapsamayla yazılır; legacy modül dokunuldukça test eklenir. Boy Scout Rule: dokunduğun dosyanın kapsamasını artır.

Yönetim ile iletişim

Coverage metriklerini yönetime sunarken bağlam verilmelidir. "%85 kapsama" tek başına anlamsızdır; "finansal hesaplama modülünde dal kapsaması %92, son çeyrek bu modülde sıfır bug" anlamlıdır. Metrik hedefi ile kalite hedefi birbirine bağlanmalıdır.

Coverage anti-pattern envanteri

Ekipler coverage hedefini tutturmak için bazen yanlış kısayollar kullanır. Bu anti-pattern'ler raporda yeşil görünür ama kaliteyi artırmaz. Code review sırasında test kodu en az uygulama kodu kadar titiz incelenmelidir.

  • Boş [Fact] veya [Test] metodu yalnızca coverage collector tetikler
  • Integration testte mock ile tüm dal bypass edilir
  • Private method testi public API davranışını gölger
  • Catch-test-exception bloğu assertion içermez
  • Snapshot test güncellenir ama içerik doğrulanmaz

SonarQube ve kalite kapısı entegrasyonu

SonarQube quality gate, coverage eşiğini PR merge koşulu yapar. New code coverage ayrı izlenir; overall coverage legacy borcu gizlemez. Quality gate failed durumunda pipeline kırılır; override yalnızca security hotfix prosedüründe mümkündür.

Çoklu modül ve monorepo kapsama

Monorepo yapısında her paketin kapsama raporu ayrı üretilir. Root dashboard paket bazında kırmızı modülleri gösterir. Paylaşılan library'de düşük kapsama tüm tüketicileri etkiler; bu modüller öncelikli test yatırımı alır. Paketler arası coverage aggregate yalnızca özet amaçlıdır; karar paket düzeyinde verilir.

Coverage ve code review

PR review checklist'ine kapsama diff ekran görüntüsü eklenir. Reviewer yalnızca yeşil yüzdeye bakmaz; kırmızı satırların risk seviyesini değerlendirir. Kritik dal test edilmemişse PR merge edilmez. Coverage aracının PR yorum botu otomatik diff raporu bırakır.

Kapsama metrikleri doğru kullanıldığında test yatırımının nereye yapılacağını gösteren güçlü bir pusuladır. Yanlış kullanıldığında yeşil ışık yanıp gerçek risk gizlenir. Dal kapsaması, diff coverage ve mutasyon skorunu birlikte izleyen ekipler hem hız hem güvenilirlik kazanır.

Branch coverage pratik örneği

Bir indirim fonksiyonunda üç dal vardır: premium müşteri, standart müşteri ve geçersiz girdi. Satır kapsaması %100 görünse bile yalnızca premium dal test edilmiş olabilir. Branch coverage raporu diğer iki kolun kırmızı olduğunu gösterir. Test mühendisi eksik senaryoları aynı gün tamamlar.