Test yazmanın en yorucu kısmı, çoğu zaman test değil testten önceki hazırlıktır. On satırlık kurulum, dört sahte kayıt, iki tarih, bir rol. Beşinci testten sonra herkes aynı kurulumu kopyalamaya başlar, altıncıdan sonra kopyalar birbirinden kopar. Oluşumlu test (generative test), bu hazırlığı kodun değil mimarinin yapmasını önerir: veri kendini kurar, test yalnızca niyetini yazar. Bu yazının önerisi tek cümledir: kurulumu fabrikalara, temizliği seed'lere, tekrarı sayaçlara devredin; test dosyanızda yalnızca davranış kalsın.

Kurulumu fabrikaya devretmek

Fikir basittir: testin ihtiyacı olan nesneyi elle yazmak yerine, onu üreten bir fabrikaya istekte bulunmaktır. Fabrikanın varsayılanları makul olur; test yalnızca kendisiyle ilgili alanları ezer. Böylece okuyan kişi, testin neyi kanıtlamaya çalıştığını ilk satırda görür. Fabrikanın bir de gizli yararı vardır: domain'de yeni bir zorunlu alan eklendiğinde tek yeri güncellersiniz, yüz test dosyasını değil.

// factories.ts — makul varsayılanlar tek yerde
export const yorumYap = (uzeri: Partial<Yorum> = {}): Yorum => ({
  id: `y-${sayaç.next()}`,
  kullanici: "ayse",
  icerik: "deneme yorumu",
  durum: "beklemede",
  ...uzeri,
});

// testte yalnızca amacı görünür
it("reddedilen yorum yayına çıkmaz", () => {
  const yorum = yorumYap({ durum: "reddedildi" });
  expect(yayinla(yorum)).toBe(false);
});

Bu küçük devşirme, testin okunabilirliğini değiştirir: şimdi test neyin önemli olduğunu söylüyor, geri kalanını gürültüye bırakıyor. Fabrikanın varsayılanı değiştiğinde tek yeri düzeltirsiniz; yüz test satırını değil. Okuma yönü de değişir: testte görünen her alan, o testin gerçek konusudur. Görünmeyen alanlar ise konu değildir; onları görmezden gelmek, okuyanın hakkıdır.

Veri tabanını da kurmak

Entegrasyon testlerinde tablo doldurmak ayrı bir derttir. Çözüm aynı ilkenin veritabanına uygulanmasıdır: seed fonksiyonları veriyi kuran, temizleyen ve şemayı doğrulayan tek gerçek kaynak olur. Her test kendi verisini kurar, kendi verisini söker; paralel koşan testler birbirinin satırlarına basmaz.

beforeEach(async () => {
  await db.delete(comments);
  await seedYorum({ adet: 3, durum: "beklemede" });
});

Bu yaklaşımın görünmeyen kazancı da vardır: şema değiştiğinde hatalar seed katmanında toplanır. Üretim veritabanına eklenen yeni bir kolon, önce seed'i kırar; testin kendisi değil, hazırlık katmanı uyaran olur. Böylece şema ile test arasındaki mesafe kısalır, hata kaynağına daha yakın çıkar.

Seed'i tek kaynak yapan bir başka kural da tekrarın yönetimidir: aynı seed'i farklı testler farklı ihtiyaçlarla çağırır, ihtiyaç fazlası veri üretmemeye özen gösterir. Gereğinden büyük seed, testin kendisinden yavaş hale gelebilir.

Fabrikanın sınırları

Oluşumlu test her derde deva değildir. Domain'in kuralları çok karmaşıksa, fabrika onun taklidi olan ikinci bir domain yaratmaya başlar; bu kez bakım yükü ikiye katlanır. Fabrikanın işi gerçeği taklit etmek değil, testin niyetini gürültüden ayırmaktır. Kurallar karmaşıklaştıysa fabrikayı büyütmek yerine, testi küçültüp gerçek dünya verisinin küçük bir örneğini kullanın.

Son söz: kurulum kodu ne kadar görünmezse, test o kadar dürüst olur. Veriyi kurun, testi yazın — tersini yapmayın; yaparsanız test dosyanız kurulum kopyalama defterine dönüşür.