Skip to content

Testing Best Practices

Giriş

Testing Best Practices (Test En İyi Uygulamaları), yazılım testlerinin etkinliğini, bakımını ve kalitesini artırmak için kullanılan yöntem ve prensiplerdir. Bu uygulamalar, test sürecinin verimliliğini ve güvenilirliğini sağlar.

Test Yazımı Best Practices

  1. Test İsimlendirme
  2. Açıklayıcı ve anlaşılır isimler
  3. Test_Koşul_BeklenenSonuç formatı
  4. İngilizce kullanımı
  5. Anlamlı kısaltmalar

  6. Test Organizasyonu

  7. Mantıksal gruplandırma
  8. Test kategorileri
  9. Test sıralaması
  10. Bağımlılık yönetimi

  11. Test Verileri

  12. Gerçekçi test verileri
  13. Test verisi yönetimi
  14. Veri temizleme
  15. Veri izolasyonu

.NET'te Test Best Practices

Test Sınıfı Örneği

public class UserServiceTests
{
    private readonly Mock<IUserRepository> _mockRepository;
    private readonly UserService _service;

    public UserServiceTests()
    {
        _mockRepository = new Mock<IUserRepository>();
        _service = new UserService(_mockRepository.Object);
    }

    [Fact]
    public async Task GetUser_WhenUserExists_ShouldReturnUser()
    {
        // Arrange
        var userId = 1;
        var expectedUser = new User { Id = userId, Name = "Test User" };
        _mockRepository.Setup(x => x.GetById(userId))
                      .ReturnsAsync(expectedUser);

        // Act
        var result = await _service.GetUser(userId);

        // Assert
        Assert.Equal(expectedUser, result);
        _mockRepository.Verify(x => x.GetById(userId), Times.Once);
    }
}

Test Kategorileri

[Trait("Category", "Integration")]
public class DatabaseTests
{
    [Fact]
    public async Task SaveUser_ShouldWork()
    {
        // Test logic
    }
}

[Trait("Category", "Performance")]
public class PerformanceTests
{
    [Fact]
    public async Task ProcessLargeData_ShouldCompleteInTime()
    {
        // Test logic
    }
}

Test Verisi Yönetimi

public static class TestData
{
    public static User CreateValidUser()
    {
        return new User
        {
            Id = 1,
            Name = "Test User",
            Email = "test@example.com"
        };
    }

    public static List<User> CreateUserList(int count)
    {
        return Enumerable.Range(1, count)
            .Select(i => new User { Id = i, Name = $"User {i}" })
            .ToList();
    }
}

Test Bakımı Best Practices

  1. Kod Organizasyonu
  2. DRY (Don't Repeat Yourself) prensibi
  3. Test yardımcı metodları
  4. Test base sınıfları
  5. Test utilities

  6. Test Temizliği

  7. Test verilerini temizleme
  8. Kaynakları serbest bırakma
  9. Test izolasyonu
  10. Test bağımsızlığı

  11. Test Dokümantasyonu

  12. Test amaçlarını belgeleme
  13. Test senaryolarını açıklama
  14. Test verilerini belgeleme
  15. Test sonuçlarını raporlama

Mülakat Soruları ve Cevapları

Temel Sorular

  1. Test yazarken dikkat edilmesi gereken en önemli prensipler nelerdir?
  2. Cevap:

    • Test bağımsızlığı
    • Açıklayıcı test isimleri
    • Tek bir şeyi test etme
    • Arrange-Act-Assert pattern
    • Test edilebilir kod yazma
  3. Test isimlendirme kuralları nelerdir?

  4. Cevap:

    • Test_Koşul_BeklenenSonuç formatı
    • Açıklayıcı ve anlaşılır isimler
    • İngilizce kullanımı
    • Anlamlı kısaltmalar
    • Tutarlı isimlendirme
  5. Test verileri nasıl yönetilmelidir?

  6. Cevap:

    • Gerçekçi test verileri
    • Test verisi fabrikaları
    • Veri temizleme stratejileri
    • Veri izolasyonu
    • Test verisi yönetimi
  7. Test bakımı nasıl yapılmalıdır?

  8. Cevap:

    • DRY prensibi
    • Test yardımcı metodları
    • Test base sınıfları
    • Test utilities
    • Düzenli refactoring
  9. Test dokümantasyonu neden önemlidir?

  10. Cevap:
    • Test amaçlarını açıklar
    • Test senaryolarını belgeler
    • Test verilerini açıklar
    • Test sonuçlarını raporlar
    • Test sürecini iyileştirir

Teknik Sorular

  1. Test base sınıfı nasıl oluşturulur?
  2. Cevap:

    public abstract class TestBase : IDisposable
    {
        protected readonly Mock<IUserRepository> MockRepository;
        protected readonly UserService Service;
        protected readonly TestData TestData;
    
        protected TestBase()
        {
            MockRepository = new Mock<IUserRepository>();
            Service = new UserService(MockRepository.Object);
            TestData = new TestData();
        }
    
        public void Dispose()
        {
            // Cleanup logic
        }
    }
    
    public class UserServiceTests : TestBase
    {
        [Fact]
        public async Task GetUser_ShouldWork()
        {
            // Test logic using base class members
        }
    }
    

  3. Test verisi fabrikası nasıl oluşturulur?

  4. Cevap:

    public static class TestDataFactory
    {
        public static User CreateUser(int? id = null, string name = null)
        {
            return new User
            {
                Id = id ?? 1,
                Name = name ?? "Test User",
                Email = "test@example.com"
            };
        }
    
        public static List<User> CreateUserList(int count)
        {
            return Enumerable.Range(1, count)
                .Select(i => CreateUser(i, $"User {i}"))
                .ToList();
        }
    }
    

  5. Test kategorileri nasıl kullanılır?

  6. Cevap:

    [Trait("Category", "Integration")]
    public class IntegrationTests
    {
        [Fact]
        public async Task DatabaseTest()
        {
            // Test logic
        }
    }
    
    [Trait("Category", "Performance")]
    public class PerformanceTests
    {
        [Fact]
        public async Task PerformanceTest()
        {
            // Test logic
        }
    }
    

  7. Test yardımcı metodları nasıl oluşturulur?

  8. Cevap:

    public static class TestHelper
    {
        public static void SetupMock<T>(Mock<T> mock, Expression<Action<T>> expression)
            where T : class
        {
            mock.Setup(expression);
        }
    
        public static void VerifyMock<T>(Mock<T> mock, Expression<Action<T>> expression, Times times)
            where T : class
        {
            mock.Verify(expression, times);
        }
    
        public static async Task<T> ExecuteWithTimeout<T>(Func<Task<T>> action, int timeoutSeconds = 5)
        {
            var task = action();
            if (await Task.WhenAny(task, Task.Delay(timeoutSeconds * 1000)) == task)
            {
                return await task;
            }
            throw new TimeoutException();
        }
    }
    

  9. Test izolasyonu nasıl sağlanır?

  10. Cevap:
    public class IsolatedTests : IDisposable
    {
        private readonly string _testDatabase;
        private readonly DbContext _context;
    
        public IsolatedTests()
        {
            _testDatabase = $"TestDb_{Guid.NewGuid()}";
            _context = new DbContext($"Server=.;Database={_testDatabase};Trusted_Connection=True;");
        }
    
        [Fact]
        public async Task TestWithIsolation()
        {
            // Test logic with isolated database
        }
    
        public void Dispose()
        {
            _context.Database.EnsureDeleted();
            _context.Dispose();
        }
    }
    

Pratik Sorular

  1. Aşağıdaki test sınıfını best practices'e göre düzenleyin:

    public class ProductServiceTests
    {
        [Fact]
        public void Test1()
        {
            var mock = new Mock<IRepository>();
            var service = new ProductService(mock.Object);
            var result = service.GetProduct(1);
            Assert.NotNull(result);
        }
    
        [Fact]
        public void Test2()
        {
            var mock = new Mock<IRepository>();
            var service = new ProductService(mock.Object);
            var result = service.GetProduct(2);
            Assert.Null(result);
        }
    }
    

  2. Cevap:

    public class ProductServiceTests : IDisposable
    {
        private readonly Mock<IRepository> _mockRepository;
        private readonly ProductService _service;
    
        public ProductServiceTests()
        {
            _mockRepository = new Mock<IRepository>();
            _service = new ProductService(_mockRepository.Object);
        }
    
        [Fact]
        public async Task GetProduct_WhenProductExists_ShouldReturnProduct()
        {
            // Arrange
            var productId = 1;
            var expectedProduct = new Product { Id = productId, Name = "Test Product" };
            _mockRepository.Setup(x => x.GetById(productId))
                          .ReturnsAsync(expectedProduct);
    
            // Act
            var result = await _service.GetProduct(productId);
    
            // Assert
            Assert.Equal(expectedProduct, result);
            _mockRepository.Verify(x => x.GetById(productId), Times.Once);
        }
    
        [Fact]
        public async Task GetProduct_WhenProductNotExists_ShouldReturnNull()
        {
            // Arrange
            var productId = 2;
            _mockRepository.Setup(x => x.GetById(productId))
                          .ReturnsAsync((Product)null);
    
            // Act
            var result = await _service.GetProduct(productId);
    
            // Assert
            Assert.Null(result);
            _mockRepository.Verify(x => x.GetById(productId), Times.Once);
        }
    
        public void Dispose()
        {
            // Cleanup if needed
        }
    }
    

  3. Aşağıdaki test verisi yönetimini best practices'e göre düzenleyin:

    public class OrderServiceTests
    {
        [Fact]
        public void TestOrder()
        {
            var order = new Order
            {
                Id = 1,
                CustomerId = 1,
                Items = new List<OrderItem>
                {
                    new OrderItem { ProductId = 1, Quantity = 2 },
                    new OrderItem { ProductId = 2, Quantity = 1 }
                }
            };
            // Test logic
        }
    }
    

  4. Cevap:

    public static class OrderTestData
    {
        public static Order CreateValidOrder(int? id = null, int? customerId = null)
        {
            return new Order
            {
                Id = id ?? 1,
                CustomerId = customerId ?? 1,
                Items = new List<OrderItem>
                {
                    CreateOrderItem(1, 2),
                    CreateOrderItem(2, 1)
                }
            };
        }
    
        public static OrderItem CreateOrderItem(int productId, int quantity)
        {
            return new OrderItem
            {
                ProductId = productId,
                Quantity = quantity
            };
        }
    }
    
    public class OrderServiceTests
    {
        [Fact]
        public async Task ProcessOrder_WhenValid_ShouldSucceed()
        {
            // Arrange
            var order = OrderTestData.CreateValidOrder();
            // Test logic
        }
    }
    

İleri Seviye Sorular

  1. Test edilebilir kod nasıl yazılır?
  2. Cevap:

    • Dependency Injection kullanın
    • Interface'leri tercih edin
    • Single Responsibility prensibini uygulayın
    • Bağımlılıkları minimize edin
    • Test edilebilir tasarım desenleri kullanın
  3. Test performansı nasıl optimize edilir?

  4. Cevap:

    • Paralel test çalıştırın
    • Test verilerini optimize edin
    • Test ortamını yapılandırın
    • Gereksiz testleri kaldırın
    • Test süresini ölçün
  5. Test bakım maliyeti nasıl azaltılır?

  6. Cevap:

    • Test kodunu modülerleştirin
    • Test yardımcı metodları kullanın
    • Test verilerini merkezileştirin
    • Test dokümantasyonunu güncel tutun
    • Düzenli refactoring yapın
  7. Test kalitesi nasıl ölçülür?

  8. Cevap:

    • Test coverage'ı ölçün
    • Test başarı oranını takip edin
    • Test süresini ölçün
    • Test bakım maliyetini hesaplayın
    • Test dokümantasyonunu değerlendirin
  9. Test stratejisi nasıl geliştirilir?

  10. Cevap:
    • Test hedeflerini belirleyin
    • Test tiplerini seçin
    • Test araçlarını belirleyin
    • Test sürecini tanımlayın
    • Test metriklerini belirleyin