Hampir seluruh 1.562 baris test TopicReview ditulis Claude. Saya hanya review — lebih dari dua minggu di produksi, semua commit lanjutan menambah test, tak ada yang menulis ulang. Tulisan ini soal kenapa test adalah target ideal untuk didelegasikan, apa yang dilihat dan diabaikan saat review (termasuk satu edge case nyata yang hilang di spec), dan konfigurasi default pembagian ini.
Tulisan sebelumnya ditutup dengan "119 spec hijau" untuk TopicReview. Pertanyaan berikutnya yang wajar ditanyakan: siapa yang menulis test itu?
Jawaban: Claude menulis hampir semua 1.562 baris kode test. Saya hanya review. Sudah lebih dua minggu di produksi, dan pola perawatan 1.562 baris itu adalah hanya menambah test baru, tak pernah menulis ulang yang lama.
Tulisan ini soal kenapa test adalah target delegasi terbaik untuk Claude, apa yang dilihat dan diabaikan saat review, dan sejauh mana pembagian ini bertahan di lapangan.
Test TopicReview tersebar di 7 file:
spec/services/topic_review_service_spec.rb 760 baris (88 test)
spec/requests/topic_reviews_spec.rb 281 baris (32 test)
spec/requests/review_appeals_spec.rb 152 baris (16 test)
spec/requests/review_votes_spec.rb 127 baris
spec/policies/topic_review_policy_spec.rb 109 baris
spec/jobs/close_topic_review_job_spec.rb 71 baris (7 test)
spec/models/topic_review_spec.rb 62 baris
───────────────────────────────────────────
1.562 baris
Meliputi empat jenis test: service (logika bisnis), request (controller + integrasi), policy (otorisasi Pundit), job (tugas terjadwal).
Commit awal d162f1e membawa Co-Authored-By: Claude Sonnet 4.6 dan mendaratkan 1.100+ baris itu sekaligus. Semua commit terkait spec setelahnya adalah "Add test for..."—tak ada satu pun refactor atau rewrite:
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
Menambal celah, bukan mengulang. Detail ini akan penting lagi nanti.
Empat alasan keras:
1. Input dan output eksplisit. Test pada hakikatnya "diberi state ini → harapkan perilaku ini". Itu justru kekuatan Claude: menerjemahkan spesifikasi ke assertion. Kode bisnis kadang butuh pertimbangan, test tidak.
2. Mekanis × volume tinggi. Satu describe .open! harus mencakup "ada juri / tak ada juri / tak ada topic / review sudah aktif"—empat context, masing-masing 2–5 it. Manusia mulai memotong di context ketiga. Claude menulis it ke-88 dengan ketelitian yang sama seperti yang pertama.
3. Loop umpan balik sangat pendek. Tulis test, jalankan rspec, hitungan detik tahu lulus atau tidak. Kode bisnis butuh hari pemakaian nyata untuk memunculkan masalah. Loop pendek = kesalahan Claude langsung ditangkap rspec—kamu tak perlu mengawasi.
4. Paralel secara alamiah. Blok it saling independen, tak ada kopling tersembunyi, mudah diskalakan. Menghasilkan puluhan test terisolasi sekaligus persis yang Claude kuasai.
Ini poros dari seluruh pembagian.
Abaikan:
Lihat:
Poin terakhir adalah nilai sejati review. Claude mencakup test "yang terpikir olehnya", tapi test yang tak terpikir olehnya tidak ditulis otomatis. Di situlah review manusia berperan—mundur dari aturan bisnis ke cakupan yang hilang.
Buka awal describe ".open!" di spec/services/topic_review_service_spec.rb:
describe ".open!" do
context "when there are eligible jurors" do
# status review benar / post under_review / assignments dibuat / author di-notify / jurors di-notify / tak dobel open
end
context "when there are no eligible jurors" do
# review dibuat tapi assignments tidak
end
context "when post has no topic" do
# kembalikan nil
end
end
Kelihatannya komprehensif. Tapi aturan nyata eligible_jurors di model mengecualikan tiga kelompok:
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
Sekarang lihat test—test mana yang menyatakan "penulis post tak akan dipilih sebagai juri"?
Telusuri service_spec.rb dan model_spec.rb: tak ada. model_spec.rb hanya menguji beberapa kasus scope pending_vote_by; tak menyentuh eligible_jurors langsung. service_spec.rb hanya punya satu komentar: # Jurors must NOT be the post author—itu komentar setup, bukan assertion.
Inilah yang bisa ditangkap review: tiga aturan pengecualian (penulis / pelapor / sudah-vote-inisial), tak satu pun dilindungi test. Kalau nanti seseorang me-refactor eligible_jurors dan tanpa sengaja menghapus post.user_id dari daftar pengecualian, semua test yang ada lolos—dan produksi diam-diam membiarkan penulis duduk di kursi jurinya sendiri.
Claude tidak salah—ia menguji yang diminta diuji. Ia hanya tak menanyakan sendiri: "apakah masing-masing dari tiga aturan ini perlu cakupan test?" Pertanyaan itu—dari aturan balik ke cakupan—itulah yang dikerjakan review.
(Jujur saja: saya juga melewatkan ini di review awal. Baru tertangkap saat audit kedua sambil menulis posting ini. Jadi review pun bukan one-shot—tapi tetap 10× lebih baik daripada tanpa review.)
Kalau "Claude menulis + manusia review" sempurna, tak akan ada commit test baru setelah yang pertama. Realitasnya lebih menarik—menambal tanpa menulis ulang:
00393fc Add test for finalize! with zero votes (expired review)
3f53304 Add test for finalize! with legacy votes missing reasoning
Yang pertama adalah regression test pasca-bug—e8cb2db Default to keep verdict when review expires with zero votes adalah fix, 00393fc adalah test pelengkapnya. Pola yang sama untuk yang kedua, mengekor abaa22e Fix CloseTopicReviewJob failing due to reasoning validation on old votes.
Dua commit ini membuktikan dua hal sekaligus:
"Cukup baik + bisa terus ditambal" adalah standar yang jauh lebih realistis daripada "sempurna". Mengejar review sempurna justru menghentikan kamu mendelegasikan test ke Claude. Menerima 'cukup baik' yang membuat pembagian ini berjalan.
Tak semua test cocok untuk handoff penuh:
Dalam kasus ini manusia memimpin dan Claude membantu.
Menjadikan pembagian ini default yang bisa dijalankan:
Programmer punya energi mental lebih sedikit untuk membaca test daripada membaca kode. Test repetitif, mekanis, melelahkan, tapi perlu. Semua itu persis titik kuat Claude—tak bosan, tak lelah, tak memotong jalan di it ke-50.
Pekerjaanmu bukan "menulis test"—tapi "memastikan setiap aturan bisnis tercakup oleh test". Satu adalah implementasi, satu lagi penilaian. Penilaian tinggal padamu; implementasi pergi ke Claude.
119 spec / 1.562 baris ship dalam satu commit dan bertahan dua minggu lebih tanpa rework—bukan karena saya menulis test lebih baik, tapi karena saya sama sekali tidak menulis. Saya hanya melakukan satu hal lebih dari Claude: memutuskan aturan bisnis mana yang layak dilindungi.