Skip to content

Test Coverage

Giriş

Test Coverage (Test Kapsamı), yazılım kodunun ne kadarının test edildiğini ölçen bir metriktir. Bu metrik, test sürecinin etkinliğini değerlendirmek ve test edilmemiş kod bölümlerini belirlemek için kullanılır.

Test Coverage'ın Önemi

  1. Kalite Güvence
  2. Kod kalitesini ölçme
  3. Test edilmemiş kodları belirleme
  4. Potansiyel hataları tespit etme

  5. Risk Yönetimi

  6. Riskli kod bölümlerini belirleme
  7. Test önceliklerini belirleme
  8. Hata olasılığını azaltma

  9. Süreç İyileştirme

  10. Test sürecini optimize etme
  11. Test stratejisini geliştirme
  12. Kaynak kullanımını iyileştirme

Test Coverage Türleri

  1. Statement Coverage
  2. Kod satırlarının test edilme oranı
  3. En temel kapsam metriği
  4. Her ifadenin en az bir kez çalıştırılması

  5. Branch Coverage

  6. Koşullu ifadelerin test edilme oranı
  7. Her dalın en az bir kez çalıştırılması
  8. If-else, switch-case gibi yapıların kontrolü

  9. Function Coverage

  10. Fonksiyonların test edilme oranı
  11. Her fonksiyonun en az bir kez çağrılması
  12. Metod düzeyinde kapsam

  13. Path Coverage

  14. Kod yollarının test edilme oranı
  15. En kapsamlı metrik
  16. Tüm olası yolların test edilmesi

.NET'te Test Coverage

Coverlet Kullanımı

// .NET CLI ile
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover

// MSBuild ile
<PropertyGroup>
  <CollectCoverage>true</CollectCoverage>
  <CoverletOutputFormat>opencover</CoverletOutputFormat>
</PropertyGroup>

ReportGenerator ile Raporlama

// Rapor oluşturma
dotnet tool install -g dotnet-reportgenerator-globaltool
reportgenerator -reports:coverage.cobertura.xml -targetdir:coveragereport

Örnek Test Projesi

public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public int Subtract(int a, int b)
    {
        return a - b;
    }
}

public class CalculatorTests
{
    [Fact]
    public void Add_ShouldReturnCorrectSum()
    {
        // Arrange
        var calculator = new Calculator();

        // Act
        var result = calculator.Add(2, 3);

        // Assert
        Assert.Equal(5, result);
    }

    [Fact]
    public void Subtract_ShouldReturnCorrectDifference()
    {
        // Arrange
        var calculator = new Calculator();

        // Act
        var result = calculator.Subtract(5, 3);

        // Assert
        Assert.Equal(2, result);
    }
}

Test Coverage Best Practices

  1. Hedef Belirleme
  2. Gerçekçi hedefler koyma
  3. Kritik kodlar için yüksek hedefler
  4. Legacy kod için makul hedefler

  5. Ölçüm Stratejisi

  6. Düzenli ölçüm yapma
  7. Farklı coverage türlerini kullanma
  8. Trend analizi yapma

  9. İyileştirme Stratejisi

  10. Düşük coverage'ı önceliklendirme
  11. Test edilebilir kod yazma
  12. Test otomasyonunu artırma

Mülakat Soruları ve Cevapları

Temel Sorular

  1. Test Coverage nedir ve neden önemlidir?
  2. Cevap: Test Coverage, yazılım kodunun ne kadarının test edildiğini ölçen bir metriktir. Önemi:

    • Kod kalitesini ölçer
    • Test edilmemiş kodları belirler
    • Risk yönetimini sağlar
    • Test sürecini iyileştirir
    • Kalite güvencesi sağlar
  3. Farklı Test Coverage türleri nelerdir?

  4. Cevap:

    • Statement Coverage: Kod satırlarının test edilme oranı
    • Branch Coverage: Koşullu ifadelerin test edilme oranı
    • Function Coverage: Fonksiyonların test edilme oranı
    • Path Coverage: Kod yollarının test edilme oranı
  5. Test Coverage hedefi ne olmalıdır?

  6. Cevap:

    • Kritik kodlar için %80-90
    • Genel kod için %70-80
    • Legacy kod için %50-60
    • Hedefler projeye özel belirlenmeli
    • Kalite güvencesi için yeterli olmalı
  7. Test Coverage'ın avantajları ve dezavantajları nelerdir?

  8. Cevap:

    • Avantajlar:
    • Kod kalitesini ölçer
    • Riskleri belirler
    • Test sürecini iyileştirir
    • Dezavantajlar:
    • Yüksek coverage kalite garantisi değil
    • Test maliyetini artırabilir
    • Yanlış güven hissi verebilir
  9. Test Coverage nasıl ölçülür?

  10. Cevap:
    • Coverlet gibi araçlar kullanılır
    • CI/CD pipeline'da entegre edilir
    • Raporlar oluşturulur
    • Trend analizi yapılır
    • Düzenli ölçüm yapılır

Teknik Sorular

  1. Coverlet nasıl kullanılır?
  2. Cevap:

    <ItemGroup>
      <PackageReference Include="coverlet.msbuild" Version="3.1.2">
        <PrivateAssets>all</PrivateAssets>
        <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      </PackageReference>
    </ItemGroup>
    
    <PropertyGroup>
      <CollectCoverage>true</CollectCoverage>
      <CoverletOutputFormat>opencover</CoverletOutputFormat>
      <CoverletOutput>./coverage/</CoverletOutput>
    </PropertyGroup>
    

  3. Test Coverage raporu nasıl oluşturulur?

  4. Cevap:

    # Rapor oluşturma
    dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
    reportgenerator -reports:coverage.cobertura.xml -targetdir:coveragereport
    

  5. Belirli bir sınıfın coverage'ı nasıl ölçülür?

  6. Cevap:

    <PropertyGroup>
      <CollectCoverage>true</CollectCoverage>
      <CoverletOutputFormat>opencover</CoverletOutputFormat>
      <Include>[Namespace]*</Include>
      <Exclude>[Namespace].Tests*</Exclude>
    </PropertyGroup>
    

  7. Test Coverage nasıl artırılır?

  8. Cevap:

    // Örnek: Eksik test senaryolarını ekleme
    public class CalculatorTests
    {
        [Theory]
        [InlineData(2, 3, 5)]
        [InlineData(-1, 1, 0)]
        [InlineData(0, 0, 0)]
        public void Add_ShouldReturnCorrectSum(int a, int b, int expected)
        {
            var calculator = new Calculator();
            var result = calculator.Add(a, b);
            Assert.Equal(expected, result);
        }
    }
    

  9. Test Coverage nasıl izlenir?

  10. Cevap:
    # GitHub Actions örneği
    name: Test Coverage
    
    on: [push, pull_request]
    
    jobs:
      coverage:
        runs-on: ubuntu-latest
        steps:
        - uses: actions/checkout@v2
        - name: Setup .NET
          uses: actions/setup-dotnet@v1
        - name: Test with coverage
          run: dotnet test /p:CollectCoverage=true
        - name: Generate report
          run: reportgenerator -reports:coverage.cobertura.xml -targetdir:coveragereport
    

Pratik Sorular

  1. Aşağıdaki sınıfın test coverage'ını artırın:

    public class UserValidator
    {
        public bool Validate(User user)
        {
            if (user == null)
                return false;
    
            if (string.IsNullOrEmpty(user.Name))
                return false;
    
            if (user.Age < 18)
                return false;
    
            return true;
        }
    }
    

  2. Cevap:

    public class UserValidatorTests
    {
        [Theory]
        [InlineData(null, false)]
        [InlineData("", false)]
        [InlineData("John", 17, false)]
        [InlineData("John", 18, true)]
        [InlineData("John", 25, true)]
        public void Validate_ShouldReturnCorrectResult(string name, int age, bool expected)
        {
            // Arrange
            var validator = new UserValidator();
            var user = name != null ? new User { Name = name, Age = age } : null;
    
            // Act
            var result = validator.Validate(user);
    
            // Assert
            Assert.Equal(expected, result);
        }
    }
    

  3. Aşağıdaki servisin test coverage'ını ölçün:

    public class PaymentService
    {
        private readonly IPaymentGateway _gateway;
        private readonly ILogger _logger;
    
        public PaymentService(IPaymentGateway gateway, ILogger logger)
        {
            _gateway = gateway;
            _logger = logger;
        }
    
        public async Task<PaymentResult> ProcessPayment(PaymentRequest request)
        {
            try
            {
                if (request.Amount <= 0)
                    return new PaymentResult { Success = false, Message = "Invalid amount" };
    
                var result = await _gateway.Process(request);
    
                if (result.Success)
                    _logger.LogInformation($"Payment processed: {request.Amount}");
                else
                    _logger.LogError($"Payment failed: {result.Message}");
    
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Payment processing failed");
                return new PaymentResult { Success = false, Message = "Internal error" };
            }
        }
    }
    

  4. Cevap:

    public class PaymentServiceTests
    {
        [Theory]
        [InlineData(0, false, "Invalid amount")]
        [InlineData(-100, false, "Invalid amount")]
        [InlineData(100, true, "Success")]
        public async Task ProcessPayment_ShouldHandleAmountValidation(decimal amount, bool expectedSuccess, string expectedMessage)
        {
            // Arrange
            var mockGateway = new Mock<IPaymentGateway>();
            var mockLogger = new Mock<ILogger>();
            var service = new PaymentService(mockGateway.Object, mockLogger.Object);
            var request = new PaymentRequest { Amount = amount };
    
            // Act
            var result = await service.ProcessPayment(request);
    
            // Assert
            Assert.Equal(expectedSuccess, result.Success);
            Assert.Equal(expectedMessage, result.Message);
        }
    
        [Fact]
        public async Task ProcessPayment_ShouldLogSuccess()
        {
            // Arrange
            var mockGateway = new Mock<IPaymentGateway>();
            var mockLogger = new Mock<ILogger>();
            var service = new PaymentService(mockGateway.Object, mockLogger.Object);
            var request = new PaymentRequest { Amount = 100 };
    
            mockGateway.Setup(x => x.Process(request))
                       .ReturnsAsync(new PaymentResult { Success = true });
    
            // Act
            await service.ProcessPayment(request);
    
            // Assert
            mockLogger.Verify(x => x.LogInformation(It.Is<string>(s => s.Contains("processed"))), Times.Once);
        }
    
        [Fact]
        public async Task ProcessPayment_ShouldHandleExceptions()
        {
            // Arrange
            var mockGateway = new Mock<IPaymentGateway>();
            var mockLogger = new Mock<ILogger>();
            var service = new PaymentService(mockGateway.Object, mockLogger.Object);
            var request = new PaymentRequest { Amount = 100 };
    
            mockGateway.Setup(x => x.Process(request))
                       .ThrowsAsync(new Exception("Test exception"));
    
            // Act
            var result = await service.ProcessPayment(request);
    
            // Assert
            Assert.False(result.Success);
            Assert.Equal("Internal error", result.Message);
            mockLogger.Verify(x => x.LogError(It.IsAny<Exception>(), It.Is<string>(s => s.Contains("failed"))), Times.Once);
        }
    }
    

İleri Seviye Sorular

  1. Test Coverage ve kod kalitesi arasındaki ilişki nedir?
  2. Cevap:

    • Yüksek coverage kalite garantisi değil
    • Test kalitesi önemli
    • Edge case'lerin testi önemli
    • Test maintainability önemli
    • Test readability önemli
  3. Test Coverage'ı nasıl optimize edersiniz?

  4. Cevap:

    • Kritik kodları önceliklendirin
    • Test edilebilir kod yazın
    • Test stratejisi geliştirin
    • Coverage araçlarını etkin kullanın
    • Düzenli ölçüm ve analiz yapın
  5. Test Coverage'ı CI/CD'ye nasıl entegre edersiniz?

  6. Cevap:

    • Pipeline'da coverage ölçümü
    • Coverage raporları oluşturma
    • Coverage eşikleri belirleme
    • Trend analizi yapma
    • Otomatik uyarılar oluşturma
  7. Test Coverage ve performans arasındaki denge nasıl sağlanır?

  8. Cevap:

    • Kritik kodları önceliklendirin
    • Test süresini optimize edin
    • Paralel test çalıştırın
    • Test verilerini yönetin
    • Test ortamını optimize edin
  9. Test Coverage'ı nasıl raporlarsınız?

  10. Cevap:
    • HTML raporları oluşturun
    • Trend grafikleri çizin
    • Ekip raporları hazırlayın
    • Dashboard'lar oluşturun
    • Otomatik uyarılar ayarlayın