TopicReview'un 1.562 satırlık testinin neredeyse tamamını Claude yazdı. Ben yalnızca review yapıyorum — iki haftadan uzun süredir canlıda, sonraki tüm commit'ler test ekliyor, hiçbiri yeniden yazmıyor. Bu yazı testlerin neden devretmek için en ideal iş olduğunu, review'da neye bakılıp neye bakılmadığını (gerçek spec'te eksik kalan bir edge case dahil) ve bu bölüşümün varsayılan yapılandırmasını anlatıyor.
Önceki yazı TopicReview için "119 spec yeşil" ile kapandı. Okuyucunun asıl sorması gereken bir sonraki soru: o testleri kim yazdı?
Cevap: Claude 1.562 satır test kodunun neredeyse tamamını yazdı. Ben yalnızca review ettim. İki haftayı aşkın süredir canlıda, bu 1.562 satırın bakım örüntüsü yalnızca yeni test eklemek, eskileri asla yeniden yazmamak şeklinde.
Bu yazı testlerin Claude'a devredilecek en iyi iş olmasının nedenini, review'da nelere bakılıp nelerin yok sayılacağını ve bu bölüşümün pratikte nereye kadar gittiğini anlatıyor.
TopicReview'un testleri 7 dosyaya yayılmış durumda:
spec/services/topic_review_service_spec.rb 760 satır (88 test)
spec/requests/topic_reviews_spec.rb 281 satır (32 test)
spec/requests/review_appeals_spec.rb 152 satır (16 test)
spec/requests/review_votes_spec.rb 127 satır
spec/policies/topic_review_policy_spec.rb 109 satır
spec/jobs/close_topic_review_job_spec.rb 71 satır (7 test)
spec/models/topic_review_spec.rb 62 satır
───────────────────────────────────────────
1.562 satır
Dört tür testi kapsar: service (iş mantığı), request (controller + entegrasyon), policy (Pundit yetkilendirmesi), job (zamanlanmış görevler).
İlk commit d162f1e Co-Authored-By: Claude Sonnet 4.6 etiketini taşıyor ve bu satırların 1.100'den fazlasını tek seferde getiriyor. Sonraki tüm spec ilgili commit'ler "Add test for..." biçiminde—tek bir refactor veya rewrite yok:
00393fc Add test for finalize! with zero votes (expired review)
3f53304 Add test for finalize! with legacy votes missing reasoning
3b185da Update specs to use PROVISIONAL_PENALTY constant
Boşluk yamıyor, yeniden yapmıyor. Bu ayrıntı ilerde önemli.
Dört sert sebep:
1. Girdi ve çıktılar açık. Testin özü "verilen state → beklenen davranış"tır. Bu Claude'un en iyi olduğu çeviri işidir—spec'i iddiaya dönüştürmek. İş kodunun bazen ödünleşmeye gereksinimi olur; testlerin neredeyse hiç yoktur.
2. Mekanik × yüksek hacim. Tek bir describe .open! "uygun juri var / yok / topic yok / zaten aktif review var" dört context'i kapsamak zorunda; her birinde 2–5 it. İnsan üçüncü context'te köşe kapatmaya başlar. Claude 88. it'i birinciyle aynı özenle yazar.
3. Aşırı kısa geri bildirim döngüsü. Bir test yazarsın, rspec'i çalıştırırsın, saniyeler içinde geçip geçmediğini öğrenirsin. İş kodu sorunların yüzeye çıkması için günlerce gerçek kullanım ister. Kısa döngü = Claude'un hatası rspec tarafından yerinde yakalanır—sen gözetlemek zorunda kalmazsın.
4. Doğal olarak paralel. it blokları bağımsızdır, gizli eşleşme yoktur, önemsizce ölçeklenir. Bir seferde onlarca izole test üretmek tam da Claude'un iyi olduğu şeydir.
Bütün bölüşümün ekseni burası.
Görmezden gel:
Bak:
Sonuncusu review'un gerçek değeridir. Claude "aklına gelen" testleri kapsar ama aklına gelmeyen testler kendiliğinden yazılmaz. İnsan review'u tam da buraya oturur—iş kurallarından geriye doğru çalışarak eksik kapsamayı bulmak.
spec/services/topic_review_service_spec.rb başındaki describe ".open!"u açalım:
describe ".open!" do
context "when there are eligible jurors" do
# review durumu doğru / post under_review / assignments oluşturuldu / author bildirildi / jurors bildirildi / çift open olmuyor
end
context "when there are no eligible jurors" do
# review oluşur ama assignments olmaz
end
context "when post has no topic" do
# nil döndürür
end
end
Kapsamlı görünüyor. Ama model'deki gerçek eligible_jurors kuralı üç grubu dışlıyor:
def eligible_jurors
excluded_ids = [ post.user_id ] + post.reports.pluck(:user_id) + review_votes.where(stage: :initial).pluck(:user_id)
User.jurors_and_judges.where.not(id: excluded_ids.uniq)
end
Şimdi testlere bakın—"post yazarı asla juri olarak seçilmez" iddiasını hangi test yapıyor?
service_spec.rb ve model_spec.rb'yi tarayın: yok. model_spec.rb yalnızca pending_vote_by scope'unun birkaç vakasını test ediyor; eligible_jurors'ı doğrudan kapsamıyor. service_spec.rb'de sadece bir yorum var: # Jurors must NOT be the post author—bu setup'ta bir yorum, iddia değil.
Review'un yakalayabileceği şey işte bu: üç dışlama kuralı (yazar / raporlayan / ilk turda oy kullanan), hiçbiri bir testle korunmuyor. Sonra biri eligible_jurors'u refaktör edip yanlışlıkla post.user_id'yi dışlama listesinden düşürürse, mevcut tüm testler geçer—ve production sessizce yazarların kendi jürilerinde oturmasına izin verir.
Claude yanılmadı—kendisinden istenen şeyi test etti. Yalnızca kendiliğinden şunu sormadı: "bu üç kuralın her biri test koruması gerektiriyor mu?" Bu soru—kurallardan kapsamaya geriye gitmek—review'un işidir.
(Dürüst olalım: ilk review'da bunu ben de kaçırdım. Bu yazıyı yazarken yapılan ikinci denetimde fark ettim. Yani review de tek seferlik değil—ama yine de review etmemekten 10× iyi.)
"Claude yazar + insan review eder" kusursuz olsaydı, ilk commit'ten sonra yeni test commit'i olmazdı. Gerçek daha ilgi çekici—boşluk yaması var ama yeniden yazma yok:
00393fc Add test for finalize! with zero votes (expired review)
3f53304 Add test for finalize! with legacy votes missing reasoning
İlki hata sonrası regression test—e8cb2db Default to keep verdict when review expires with zero votes fix, 00393fc eş test. İkincisi aynı örüntüyle abaa22e Fix CloseTopicReviewJob failing due to reasoning validation on old votes'ı izler.
Bu iki commit aynı anda iki şeyi kanıtlıyor:
"Yeterince iyi + yamayla sürdürülebilir" "kusursuz"dan çok daha gerçekçi bir çıta. Kusursuz review peşinde koşmak, Claude'a test devretmenizi engelleyen şey. 'Yeterince iyi'yi kabul etmek bu bölüşümü çalıştıran şey.
Her test tam devire uygun değil:
Bu durumlarda insan önderlik eder, Claude yardımcı olur.
Bu bölüşümü çalıştırılabilir bir default'a çevirmek için:
Programcının test okurken harcadığı zihinsel kaynak kod okurken harcadığından azdır. Testler tekrarlı, mekanik, yorucu ve gerekli. Bunların tümü Claude'un güçlü bölgesini tarif ediyor—sıkılmaz, yorulmaz, 50. it'te köşe kapatmaz.
Senin işin "test yazmak" değil—"her iş kuralının bir testle kapsandığından emin olmak". Biri uygulama, diğeri yargı. Yargı sende kalır; uygulama Claude'a gider.
119 spec / 1.562 satırın tek commit'te çıkıp iki haftadan fazla rework'süz hayatta kalması—daha iyi test yazdığım için değil, hiç test yazmadığım için gerçekleşti. Claude'un yapmadığı tek bir şeyi yapıyorum: hangi iş kurallarının korunmaya değer olduğuna karar veriyorum.