Ana içeriğe geç

"unit-test" ile etiketlenmiş Bir gönderi

Tüm Etiketleri Görüntüle

Mutation Testing

· 4 dakikalık okuma
Ahmet Buğra Kösen
Software Developer

x.png

Yazılım geliştirme süreçlerinde unit testler, kod kalitesini ve güvenilirliğini artırmak için vazgeçilmez bir araçtır. Ancak, unit testlerimizin gerçekten etkili olup olmadığını nasıl anlayabiliriz? İşte bu noktada Mutation Testing devreye giriyor. Bu makalede, Mutation Testing kavramını, manuel olarak nasıl uygulanabileceğini ve .NET ekosisteminde popüler bir araç olan Stryker.NET ile nasıl otomatize edilebileceğini inceleyeceğiz.


Mutation Testing Nedir?

Mutation Testing, testlerinizin etkinliğini değerlendirmek için kullanılan bir tekniktir. Bu yöntemde, kodunuzda küçük değişiklikler (mutasyonlar) yapılarak testlerinizin bu değişiklikleri yakalayıp yakalayamadığı kontrol edilir. Eğer testleriniz bu mutasyonları tespit edemezse, bu durum test senaryolarınızın geliştirilmesi gerektiğini gösterir.

Neden Önemlidir?

  • Test Kalitesini Artırır: Sadece kodun test edilip edilmediğini değil, testlerin ne kadar etkili olduğunu da ölçer.
  • Hata Yakalama Yeteneğini Geliştirir: Potansiyel hataları erken aşamada tespit etmeyi sağlar.
  • Güvenilirlik Sağlar: Kodunuzun değişikliklere karşı ne kadar dayanıklı olduğunu gösterir.

Manuel Olarak Mutation Testing Nasıl Yapılır?

Otomatik araçlar kullanmadan da mutation testing prensiplerini uygulayabilirsiniz. Bu bölümde, manuel olarak nasıl mutation testing yapabileceğinizi basit bir örnekle göstereceğiz.

Öncelikle, test etmek istediğimiz basit bir sınıf ve buna ait unit testleri yazalım.

MathOperations.cs:

namespace MutationDemo;

public class MathOperations
{
public int Add(int a, int b) => a + b;
}

Unit Test:

using Xunit;
using FluentAssertions;

namespace MutationDemo.UnitTests;

public class MathOperationsTests
{
[Fact]
public void Add_ShouldReturnCorrectSum()
{
// Arrange
var mathOperations = new MathOperations();

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

// Assert
result.Should().Be(5);
}
}

Test projesinin bulunduğu dizinde dotnet test komutu ile yazdığımız testi çalıştırdığımızda testimizin başarıyla geçtiğini göreceğiz;

Passed!  - Failed:     0, Passed:     1, Skipped:     0, Total:     1, Duration: < 1 ms

Şimdi, kodumuzda bilinçli bir hata yaparak mutasyon oluşturalım. Örneğin, + operatörünü - operatörüyle değiştirelim:

public int Add(int a, int b) => a - b;

Değişiklikleri kaydettikten sonra dotnet test komutu ile testi tekrar çalıştıralım: Test çıktısı aşağıdaki şekilde olmalı:

Failed!  - Failed:     1, Passed:     0, Skipped:     0, Total:     1, Duration: < 1 m

Testin başarısız olması, testimizin bu mutasyonu yakaladığını gösterir. Süper bir unit test yazmışız, testimiz koddaki bu hatayı tespit edebiliyor.


Diğer olası mutasyonları da deneyebilirsiniz. Örneğin, return a + b; satırını return a; olarak değiştirebiliriz:

public int Add(int a, int b) => a;

Testleri tekrar çalıştırdığınızda, testin yine başarısız olması gerekir. Eğer testler başarılı olursa, bu durum testlerinizin yeterince kapsamlı olmadığını gösterir ve testlerinizi gözden geçirmeniz gerekir.


Stryker.NET Nedir?

Manuel olarak mutation testing yapmak, küçük projelerde uygulanabilir olsa da, büyük projelerde zaman alıcı ve karmaşık olabilir. İşte bu noktada Stryker.NET devreye giriyor. Stryker.NET, .NET platformu için geliştirilmiş açık kaynaklı bir mutation testing aracıdır. Kodunuzda otomatik olarak mutasyonlar oluşturarak, testlerinizin bu mutasyonları yakalayıp yakalayamadığını analiz eder.

Özellikleri

  • Kolay Entegrasyon: Mevcut .NET projelerinize hızlıca entegre edilebilir.
  • Esnek Yapılandırma: Farklı test çerçeveleri (xUnit, NUnit, MSTest) ile uyumludur.
  • Detaylı Raporlama: Mutasyon skorları ve hangi mutasyonların tespit edilemediği gibi detaylı raporlar sunar.

Stryker.NET ile Mutation Testing

Biraz önce manuel olarak gerçekleştirdiğimiz mutasyon testini, Stryker.NET'i kullanarak aynı projede otomatikleştirelim.

Gereksinimler

  • .NET 6 veya daha yeni bir sürüm

  • Unit testler için xUnit

  • Stryker.NET'in kurulu olması

    Stryker.NET'i global bir araç olarak kurmak için komut satırında aşağıdaki komutu çalıştırın;

    dotnet tool install -g dotnet-stryker

Stryker.NET ile Mutation Testing'i Çalıştırma

Test projenizin dizininde aşağıdaki komutu çalıştırın:

dotnet stryker

Bu komut, Stryker.NET'in varsayılan ayarlarla mutation testing'i başlatmasını sağlar. Testler tamamlandıktan sonra Stryker.NET size bir rapor sunacaktır.

image.png

Stryker tarafından üretilen html raporunu incelediğimizde Stryker'ın kodun hangi kısmında kaç tane ve nasıl mutasyon oluşturduğunu görebiliriz;

image.png

Mutasyon skorunun %100 olduğunu görüyoruz. Yani bu, testlerimizi Add methodunda yaptığımız değişiklikleri kapsayacak şekilde yazdığımız anlamına geliyor.

Stryker.NET, hangi mutasyonların öldürüldüğünü (testler tarafından yakalandığını) ve hangilerinin hayatta kaldığını (testlerin yakalayamadığını) detaylı bir şekilde raporlar. Bu raporları inceleyerek, testlerinizde hangi senaryoların eksik olduğunu tespit edebilirsiniz.


Sonuç

Mutation Testing, unit testlerinizin gerçekten etkili olup olmadığını anlamak için güçlü bir yöntemdir. Manuel olarak uygulanabilir olsa da, Stryker.NET gibi araçlar sayesinde bu süreci otomatikleştirerek zaman ve emek tasarrufu sağlayabilirsiniz. Bu sayede kod kalitenizi artırabilir ve olası hataları erken aşamada tespit edebilirsiniz.

Dipnot: Emek emek yazdığım 2000’e yakın test barındıran canım kütüphanemde, mutasyon skorunun %40 olduğunu görünce yaşadığım hüsranı size tarif edemem 😟 Sizde aynı hüsranı yaşamak istemiyorsanız test yazım tekniklerinizi mutasyon raporlarını inceleyerek iyileştirebilirsiniz.

Bir sonraki yazıda görüşmek dileğiyle…