Episode ini saya mulai dengan perasaan campur aduk. Selama ini saya menulis Laravel dengan cara yang sama seperti menulis skrip: jalankan, lihat hasilnya di browser, kalau tidak error berarti sudah benar. Ternyata cara itu rapuh — perubahan kecil di satu file bisa merusak fitur lain tanpa saya sadari sampai user komplain. Hari ini saya catat cara Laravel membantu saya menguji kode secara otomatis, sekaligus kesulitan yang saya temui saat pertama kali menulis test.
Kenapa Test Itu Penting (Bukan Soal Formalitas)
Prinsip yang paling mengubah cara kerja saya: test adalah dokumen hidup. Kalau saya punya test untuk fitur “user bisa mendaftar”, saya tidak perlu takut mengubah kode auth — jalankan test, kalau hijau berarti aman. Analogi sederhananya: test itu seperti rem tangan mobil. Tidak terasa saat melaju lurus, tapi menyelamatkan saat tikungan.
Laravel sudah menyiapkan semua yang saya butuhkan di dalam kotak: PHPUnit sebagai engine, faker untuk data uji palsu, factory untuk membuat record dummy, dan artisan test sebagai pintu masuk yang ramah. Saya tidak perlu merangkai apa pun dari nol.
Dua Jenis Test yang Saya Pakai Sehari-hari
Pertama, unit test: menguji satu fungsi kecil tanpa menyentuh database atau HTTP. Kedua, feature test: menguji alur lengkap dari request masuk sampai response keluar. Untuk aplikasi web Laravel, ternyata feature test yang paling sering saya pakai karena mewakili apa yang benar-benar dilakukan user.
Contoh feature test sederhana — memastikan halaman daftar benar-benar bisa diakses dan mengembalikan data yang benar:
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class TaskControllerTest extends TestCase
{
use RefreshDatabase;
public function test_guest_can_see_task_list(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->get('/tasks');
$response->assertStatus(200);
$response->assertSee('Daftar Tugas');
}
public function test_user_can_create_task(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/tasks', [
'title' => 'Belajar Testing',
'due_date' => now()->addDays(3)->toDateString(),
]);
$response->assertRedirect();
$this->assertDatabaseHas('tasks', [
'title' => 'Belajar Testing',
'user_id' => $user->id,
]);
}
}Dua hal yang saya pelajari dari kode di atas. RefreshDatabase membuat database test di-reset tiap test selesai, jadi test satu sama lain tidak saling mengotori — ini penyelamat. Lalu actingAs($user) langsung login-kan user palsu tanpa perlu submit form login, membuat test jauh lebih ringkas.
Factory & Faker: Data Palsu yang Masuk Akal
Dulu saya sempat bingung: untuk menguji fitur yang butuh 50 data tugas, apakah saya harus membuat 50 record manual? Ternyata tidak. Factory Laravel bisa membuat data dummy dengan satu baris, dan faker otomatis mengisi nama, email, tanggal yang terlihat wajar:
<?php
namespace Database\Factories;
use App\Models\Task;
use Illuminate\Database\Eloquent\Factories\Factory;
class TaskFactory extends Factory
{
protected $model = Task::class;
public function definition(): array
{
return [
'title' => fake()->sentence(4),
'is_done' => fake()->boolean(30),
'due_date' => fake()->dateTimeBetween('now', '+7 days'),
];
}
}Kemudian di test tinggal Task::factory()->count(20)->create() — dua puluh data siap pakai dalam sekejap.
Cara Menjalankan Test & Yang Saya Alami Saat Pertama Kali
Semua test dijalankan lewat artisan:
php artisan test php artisan test --filter=TaskControllerTest php artisan test --parallel
Kesulitan nyata yang saya temui: pertama, test hijau di lokal tapi merah di CI — ternyata karena perbedaan konfigurasi database. Kedua, saya sempat menulis test yang terlalu spesifik (menghafal urutan output) sehingga mudah pecah saat kode dirapikan. Pelajaran saya: uji perilaku yang dilihat user, bukan detail implementasi internal. Ketiga, pest — alternatif modern dengan sintaks lebih ringkas — menarik tapi saya masih betah di PHPUnit karena materi dan dokumentasinya lebih banyak saya temukan.
Kesimpulan Catatan Saya
Testing terasa merepotkan di awal, tapi setelah kebiasaan terbentuk saya merasa lebih tenang mengubah kode. Kalau ada satu hal yang mau saya bawa dari episode ini: mulai dari feature test dulu untuk alur yang paling penting di aplikasi, bukan memburu cakupan test 100%. Konsistensi kecil yang dijalankan tiap kali mengubah kode lebih berharga daripada angka cakupan yang besar tapi test-nya jarang dijalankan.
Komentar Terbaru