Doğru Test Stratejilerini Kullanmak
140 testiniz var. Hepsi geçiyor. Pipeline yeşil, kaplama oranı %78’de ve “kolay” bir his veriyor.
Bir kullanıcı, siparişin oluşturulduğu ama onay e-postasının hiç ulaşmadığını rapor ediyor. Testin store metodunun mevcut olduğunu görüyorsunuz, geçiyor ve hiçbir şey sorun çıkarmıyor.
Neden? Çünkü e-postaya bakmadı. Sadece HTTP durum koduna baktı.
Yanlış Test Olarak Geçen Senaryolar
Böylesi testleri daha önceden yazdınız. Bu durumda:
public function test_cria_pedido()
{
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/pedidos', [
'produto_id' => 1,
'quantidade' => 2,
]);
$response->assertStatus(200); // 🎉 yeşil!
}
Şimdi rahatsız edici bir alıştırma: kontrolü gidin ve e-posta gönderme satırını yorumlayın.
Test hala geçiyor.
İndirim hesaplama satırını yorumlayın. Geçiyor.
Stok düşürme satırını yorumlayın. Geçiyor.
Bu test, sipariş oluşturmayı test etmiyor. Sadece rotanın mevcut olup olmadığını ve Laravel’in yolda patlak vermediğini test ediyor. Bu, çok fazla şeyin doğru olduğunu gösteren bir test. Gerçekte, bu testin anlamı yoktur.
Testlerin Gerçek Değerleri
Testlerin geçerli olup olmadığını anlamanın tek yolu, kodu bozduğunuzda testin maviye dönüşüp dönüşmediğidir. Bir test, davranış değiştiğinde başarısız olmalıdır.
Geçen bir test, kodun ne yaptığına dair bir güvence sağlamıyor, sadece güzel bir kaplama sunuyor ve aynı zamanda zaman alıyor. Bu tür testler, “test geçerdi” demenin ötesine geçmiyor.
Özelliklerin Gerçek Yeteneklerini Test Etmek
Bir sipariş oluşturmanın iş anlamı nedir? Muhtemelen: veritabanına kaydetmek, stok düşürmek, bir e-posta göndermek. Bu nedenle, testin şunları ifade etmesi gerekiyor:
public function test_cria_pedido()
{
Mail::fake();
$user = User::factory()->create();
$produto = Produto::factory()->create(['estoque' => 10]);
$response = $this->actingAs($user)->post('/pedidos', [
'produto_id' => $produto->id,
'quantidade' => 2,
]);
$response->assertRedirect('/pedidos');
// Sipariş gerçekten var, doğru verilerle
$this->assertDatabaseHas('pedidos', [
'user_id' => $user->id,
'produto_id' => $produto->id,
'quantidade' => 2,
]);
// Stok azaldı
$this->assertEquals(8, $produto->fresh()->estoque);
// E-posta, doğru kişiye gitti
Mail::assertSent(PedidoConfirmado::class, fn ($mail) => $mail->hasTo($user->email));
}
Şimdi geri dönüp e-posta satırını yorumlayın. Kırmızı. Stok satırını yorumlayın. Kırmızı.
Bu test, sistemin ne yaptığını bilmektedir. Bu nedenle, bir anlamı vardır.
Laravel’in Sağladığı Faydalar
Gördüğüm zayıf testlerin yarısı, kişinin doğrulama yapabileceğini bilmediğinden kaynaklanmaktadır. Laravel neredeyse her şeyi hazır sunar:
Mail::fake(); Mail::assertSent(BoasVindas::class);
Queue::fake(); Queue::assertPushed(ProcessarPagamento::class);
Event::fake(); Event::assertDispatched(PedidoCriado::class);
Bus::fake(); Bus::assertChained([...]);
Storage::fake('s3'); Storage::disk('s3')->assertExists('nota.pdf');
Http::fake(); Http::assertSent(fn ($req) => $req->url() === 'https://api.exemplo.com/cobranca');
Her bir satır, testiniz için görünmez olan yan etkileri ortaya çıkarır.
Test Kapsamı Bilmecesi
Yalnızca doğru yolları test etmekle kalmayın. Sadece veri girişleri ile aynı temel senaryoları yazmak, hataların genellikle yolda bulunmadığını göz önüne almanız anlamına gelir. Hatalar genellikle negatif senaryolarda gizlenir. Bu nedenle, kodu test etmeli ve başarısız olmasını sağlamalısınız.
public function test_nao_cria_pedido_sem_estoque()
{
$produto = Produto::factory()->create(['estoque' => 1]);
$response = $this->actingAs(User::factory()->create())
->post('/pedidos', ['produto_id' => $produto->id, 'quantidade' => 5]);
$response->assertSessionHasErrors('quantidade');
$this->assertDatabaseCount('pedidos', 0); // ve hiçbir şey yaratmadı
}
Unutmayın, sadece hata almanız yeterli değil — hiçbir şeyin gerçekleşmediğini de onaylamanız gerekir.
Mocklama Hataları
Bir diğer aşırı durum da, her şeyin mock edilmesi. Bu da yanıltıcı olabilir çünkü sophisticated görünür:
$repo = Mockery::mock(PedidoRepository::class);
$repo->shouldReceive('criar')->once()->andReturn(new Pedido());
$this->app->instance(PedidoRepository::class, $repo);
Her şeyi mockladıysanız, geriye ne kaldı ki test edebilesiniz? A metodunun B metodunu çağırdığını onaylamışsınız. B bozukken, test hala yeşil kalmaya devam eder.
Kapsama Oranı ve Kalite
%78 kapsama, testler sırasında %78’inin çalıştırıldığını gösterir. Ancak doğrulandıklarını göstermez. İlk testiniz, assertStatus(200) sadece controller’ın tamamını çalıştırır. Güzel bir kapsama ama hiçbir algılama yeteneği yok.
Doğru bir metrik arıyorsanız, mutation testing yöntemini uygulayın. PHP’de, Infection kullanarak kodunuzu kasıtlı olarak değiştirir (bir >yi >= ile değiştirir, bir booleanu tersine çevirir) ve hangi testlerin durumu algıladığını kontrol eder.
Sonuç Olarak
Şimdi en önemli testinizi belirleyin. O testi kontrol eden kodda bir iş kuralı satırını silin.
Yeşil mi geçti? Güvenlik ağlarınız hakkında önemli bir şey keşfettiniz.
Ve hangi hatanın tüm testleri atladığını ve üretimde patladığını düşünüyorsunuz? Yorumlarda paylaşın — ben başlıyorum: Mail::fake() bıraktığım bir testle geldi. Bir daha asla. 😅
Kaynak: Orijinal Makale


