Test ve Kalite Güvencesi

Yazılım kalitesini sağlamak için test türleri (birim, entegrasyon, sistem, kabul), test stratejileri (TDD, BDD), test otomasyonu, sürekli test, kalite metrikleri, test piramidi, test çiftleri (mock, stub), performans ve güvenlik testleri ile .NET ekosistemindeki test araçları (xUnit, NUnit, Moq, Selenium, Playwright) ve en iyi uygulamalar ele alınır.

Test ve Kalite Güvencesi

Test ve Kalite Güvencesi: Yazılım Kalitesinin Temel Taşı

Test ve Kalite Güvencesi (QA), yazılım geliştirme yaşam döngüsünün vazgeçilmez bir parçasıdır. Sadece hataları bulmak değil, aynı zamanda yazılımın gereksinimlere uygunluğunu, performansını, güvenliğini ve kullanıcı deneyimini garanti etmekle ilgilidir. Kalite güvencesi, sadece test ekibinin değil, tüm geliştirme ekibinin ortak sorumluluğudur. Bu yazıda, test türlerini, test stratejilerini, test otomasyonunu, kalite metriklerini, test piramidini, test çiftlerini ve .NET ekosisteminde kullanılan araçları derinlemesine ele alacağız.


1. Neden Test ve Kalite Güvencesi?

  • Hata Tespiti ve Önlenmesi: Kodun erken aşamalarda test edilmesi, hataların üretim ortamına ulaşmasını engeller.

  • Müşteri Memnuniyeti: Kaliteli yazılım, kullanıcı güvenini ve memnuniyetini artırır.

  • Maliyet Azaltma: Üretimde tespit edilen bir hatanın düzeltilme maliyeti, geliştirme aşamasında tespit edilene göre kat kat fazladır.

  • Risk Yönetimi: Kritik sistemlerde (finans, sağlık, havacılık) test, riskleri en aza indirmek için zorunludur.

  • Sürekli İyileştirme: Test sonuçları, kod kalitesi ve geliştirme süreçleri hakkında geri bildirim sağlar.


2. Test Seviyeleri ve Türleri

A. Test Seviyeleri (Test Levels)

Seviye Amaç Hedef Kitle Örnek Araçlar
Birim Test (Unit Test) En küçük kod parçalarının (fonksiyon, metot) doğruluğunu test etmek. Geliştiriciler xUnit, NUnit, MSTest, Moq
Entegrasyon Test (Integration Test) Birden çok modülün birlikte çalıştığını doğrulamak (veritabanı, harici API). Geliştiriciler xUnit, Testcontainers, WireMock
Sistem Test (System Test) Tüm sistemin uçtan uca (end-to-end) işlevselliğini test etmek. Test Ekibi Selenium, Playwright, Cypress
Kabul Testi (Acceptance Test) Yazılımın iş gereksinimlerine uygunluğunu doğrulamak. Ürün Sahibi, Müşteri SpecFlow (BDD), Cucumber

B. Test Türleri (Test Types)

Tür Açıklama
Fonksiyonel Test Yazılımın belirtilen işlevleri doğru şekilde yerine getirip getirmediğini test eder.
Regresyon Test Yeni yapılan değişikliklerin mevcut işlevselliği bozmadığını doğrular. (Otomasyon ile yapılması önerilir).
Performans Test Yazılımın yük altında hızını, ölçeklenebilirliğini ve kararlılığını test eder. (Load, Stress, Soak)
Güvenlik Test Yazılımdaki güvenlik açıklarını (zafiyetleri) tespit eder. (Penetrasyon testi, SAST/DAST).
Kullanılabilirlik Test (UX) Kullanıcı deneyimini, arayüz kolaylığını ve erişilebilirliği test eder.
Smoke Test En kritik işlevlerin çalışıp çalışmadığını kontrol eden hızlı bir testtir.
Kabul Testi (UAT) Kullanıcıların, yazılımı kendi ortamlarında test ederek onaylaması.

3. Test Stratejileri ve Yaklaşımları

A. Test Piramidi (Test Pyramid)
Mike Cohn tarafından popülerleştirilen test piramidi, farklı test türlerinin dağılımını optimize eder:

  • Tabanda (Çok Sayıda): Birim Testler (Hızlı, ucuz, izole).

  • Orta Seviyede: Entegrasyon Testleri.

  • Tepede (Az Sayıda): Uçtan Uca (E2E) testler (Yavaş, pahalı, kırılgan).

B. TDD (Test Driven Development)
Önce test, sonra kod yazma yaklaşımıdır. Kırmızı (başarısız test) → Yeşil (testi geçen kod) → Refactor (iyileştirme) döngüsüyle ilerler. TDD, daha modüler, test edilebilir ve hata oranı düşük kod üretir.

C. BDD (Behavior Driven Development)
TDD'nin bir uzantısı olan BDD, davranış odaklıdır. Gherkin dili (Given-When-Then) ile yazılan senaryolar, hem iş birimleri hem de geliştiriciler tarafından anlaşılabilir.

gherkin

Feature: Sipariş Oluşturma
  Scenario: Başarılı sipariş oluşturma
    Given Kullanıcı sepete ürün eklemiş
    When Sipariş oluştur butonuna tıklar
    Then Sipariş başarıyla oluşturulur

.NET'te BDD Araçları: SpecFlow, Reqnroll.

D. ATDD (Acceptance Test Driven Development)
Kabul testlerini yazılım geliştirmenin merkezine koyar.


4. Test Otomasyonu ve Sürekli Test

Otomasyon, tekrarlayan testlerin hızlı, tutarlı ve hatasız bir şekilde çalıştırılmasını sağlar.

  • Birim Test Otomasyonu: dotnet test komutu ile CI/CD pipeline'ında çalıştırılır.

  • UI Otomasyonu: Selenium, Playwright, Cypress gibi araçlar ile tarayıcı testleri otomatikleştirilir.

  • API Test Otomasyonu: Postman/Newman, RestSharp, Karate veya xUnit ile API testleri.

  • Sürekli Test: Testlerin CI/CD pipeline'ına entegre edilmesi, her kod değişikliğinde testlerin otomatik çalıştırılması ve hızlı geri bildirim sağlanmasıdır.


5. Test Çiftleri (Test Doubles)

Gerçek bağımlılıklar yerine test sırasında kullanılan sahte nesnelerdir.

Tür Açıklama .NET Örneği
Mock (Mock) Beklenen davranışlar ve doğrulamalar ile önceden programlanmış nesnelerdir. Moq, NSubstitute, FakeItEasy
Stub (Köstek) Test sırasında önceden belirlenmiş yanıtlar döndüren basit nesnelerdir. Manuel implementasyon veya Moq ile .Returns()
Fake (Sahte) Hafif, çalışabilir bir implementasyondur (ör. In-Memory veritabanı). InMemoryDatabase (EF Core)
Spy (Casus) Çağrılan metotları ve parametreleri kaydeder, daha sonra doğrulama yapılır. Moq ile .Verify()
Dummy (Hayali) Doldurulması zorunlu olmayan, boş nesnelerdir. new Object()

Moq ile Mock Örneği:

csharp

// Mock repository
var mockRepo = new Mock<IOrderRepository>();
mockRepo.Setup(repo => repo.GetByIdAsync(1))
        .ReturnsAsync(new Order { Id = 1, CustomerName = "Ahmet" });

var service = new OrderService(mockRepo.Object);
var order = await service.GetOrderAsync(1);
Assert.Equal("Ahmet", order.CustomerName);

6. Kalite Metrikleri (Quality Metrics)

  • Kod Kapsamı (Code Coverage): Testlerin kodun yüzde kaçını kapsadığını gösterir. Hedef genelde %70-80'dir. (Araç: Coverlet, SonarQube).

  • Hata Yoğunluğu (Defect Density): 1000 satır kod başına düşen hata sayısı.

  • Test Başarısızlık Oranı: Başarısız testlerin toplam testlere oranı.

  • Yanıt Süresi (Response Time): Performans testlerinde ölçülen ortalama yanıt süresi.

  • Hata Çözüm Süresi (Mean Time to Resolve - MTTR): Bir hatanın tespit edilip çözülmesi için geçen süre.


7. .NET Ekosisteminde Test Araçları

Kategori Araçlar Açıklama
Birim Test Frameworks xUnit.net, NUnit, MSTest .NET için en yaygın test framework'leri. xUnit en popüler olanıdır.
Mocking (Sahteleme) Moq, NSubstitute, FakeItEasy, Rhino Mocks Bağımlılıkları sahteleme. Moq en yaygın kullanılanıdır.
Assertion (Doğrulama) FluentAssertions, Shouldly Daha okunabilir ve akıcı (fluent) assert yapısı.
Test Veritabanı Testcontainers, SQLite In-Memory, EF Core InMemory Entegrasyon testleri için gerçek veya sahte veritabanı. Testcontainers (Docker) gerçek veritabanı başlatmak için idealdir.
UI Otomasyonu Selenium WebDriver, Playwright, Cypress (JS) Tarayıcı testleri. Playwright, modern web uygulamaları için güçlü bir alternatiftir.
API Test RestSharp, Postman (Newman), Karate, WireMock API testleri ve mock sunucular.
Performans Test k6, JMeter, NBomber, BenchmarkDotNet Yük testi, dayanıklılık testi, mikro-benchmark.
BDD (Davranış) SpecFlow, Reqnroll Gherkin dili ile kabul testleri yazmak.
Kod Kapsamı (Coverage) Coverlet, dotnet-coverage, SonarQube Test kapsamını ölçme ve raporlama.
Test Raporlama Allure, ReportPortal, Azure DevOps Test Plans Test sonuçlarını görselleştirme ve raporlama.

8. En İyi Pratikler ve Kaçınılması Gerekenler

İyi Pratik Kaçınılması Gerekenler
Testleri izole çalıştırın (diğer testlerden bağımsız). Testler arasında bağımlılık oluşturmak (sıralama bağımlılığı).
Her bir test tek bir işlevi test etsin (tek sorumluluk). Testlerin çok uzun olması ve birden çok iddia (assert) içermesi.
Testleri CI/CD pipeline'ına entegre edin. Testleri sadece yerelde çalıştırıp unutmak.
Birim testlerinde gerçek veritabanı veya harici API kullanmayın. Birim testlerinde gerçek veritabanı veya ağ çağrısı yapmak.
Test isimleri anlamlı ve açıklayıcı olmalıdır. Test1, Test2 gibi anlamsız isimler.
Test verilerini her seferinde yeniden oluşturun (setup/teardown). Testler arasında kirlenmiş veri kullanmak.
Hata mesajları açıklayıcı olmalıdır (FluentAssertions). Sadece "Test başarısız oldu" mesajı.

Sonuç:

Test ve Kalite Güvencesi, yazılım geliştirme sürecinin sadece son aşaması değil, tüm yaşam döngüsüne yayılan bir disiplindir. Birim testlerle başlayıp entegrasyon, sistem ve kabul testlerine kadar uzanan bu süreç, otomasyon ile desteklenmeli ve sürekli entegrasyon/dalgalı dağıtım (CI/CD) ile bütünleşmelidir. .NET ekosistemi, xUnit, Moq, Playwright, Testcontainers ve BenchmarkDotNet gibi güçlü araçlarla, geliştiricilerin her seviyede kalite kontrolünü verimli bir şekilde uygulamasına olanak tanır. Unutmayın: Kalite, test edilerek garanti edilir; test edilmeyen sistemler, hatalarla doludur.

Tüm yazılar