Setiap kali kita mengubah satu baris kode, sebenarnya kita sedang bertaruh: apakah fitur yang sudah jalan tidak rusak diam-diam? Test otomatis mengubah taruhan itu menjadi kepastian yang bisa diperiksa ulang dalam hitungan detik. Aplikasi kecil mungkin masih bisa diperiksa manual, tetapi begitu fitur bertambah, pemeriksaan manual menjadi mahal dan mudah terlewat. Di section ini kita bangun fondasi mindset testing: mengapa test ditulis, bentuk-bentuknya di Laravel, dan kosakata yang akan dipakai di sepanjang pembahasan.
Mengapa Menulis Test #
Alasan paling praktis adalah kepercayaan untuk refactor. Ketika seluruh perilaku penting tertutup test, kita bisa memindahkan logika, mengganti struktur tabel, atau memperbarui dependency tanpa menebak-nebak sisi mana yang rusak — test yang gagal akan menunjukkannya.
Alasan kedua adalah deteksi regresi. Bug yang pernah terjadi dan diperbaiki idealnya tidak pernah kembali. Dengan menulis test yang mereproduksi bug tersebut sebelum memperbaikinya, regresi yang sama akan langsung ketahuan.
Alasan ketiga sering terlewat: test adalah dokumentasi yang hidup. Test bernama test_post_wajib_memiliki_judul menjelaskan aturan bisnis lebih jelas daripada paragraf dokumentasi, dan test tersebut tidak pernah kedaluwarsa karena gagal ketika aturannya berubah.
Piramida Test #
Alokasi test yang sehat berbentuk piramida: semakin dekat ke dasar, jumlah test semakin banyak dan semakin cepat dieksekusi.
| Lapisan | Cakupan | Jumlah | Kecepatan |
|---|---|---|---|
| Unit test | Satu class/fungsi murni | Paling banyak | Milidetik |
| Feature test | Satu alur HTTP lengkap | Menengah | Puluhan milidetik |
| Browser test (mis. Dusk) | Interaksi JavaScript nyata | Paling sedikit | Detik per skenario |
Lapisan bawah menutup banyak kombinasi input secara murah, sehingga lapisan atas cukup menguji sedikit skenario kritis. Menulis puluhan browser test untuk logika perhitungan adalah pemborosan — cukup satu feature test yang memastikan alurnya terpasang dengan benar.
Unit, Feature, dan Integration di Laravel #
Laravel menyediakan dua direktori test bawaan. Directory tests/Unit menampung test untuk class murni tanpa framework, sedangkan tests/Feature menampung test level HTTP. Istilah integration test — test yang memverifikasi beberapa komponen bekerja bersama, misalnya controller dengan database — di Laravel lazim diliput oleh feature test, bukan direktori tersendiri.
| Aspek | Unit test | Feature test |
|---|---|---|
| Yang diuji | Satu class, mis. PriceCalculator | Satu request lengkap: route → middleware → controller → database |
| Framework | PHPUnit\Framework\TestCase, tanpa aplikasi | Tests\TestCase, aplikasi di-boot penuh |
| Kecepatan | Milidetik | Puluhan milidetik per test |
| Contoh | total(50000, 2, 10) mengembalikan 90000 | POST /posts menyimpan post dan muncul di GET /posts |
Kosakata Dunia Testing #
Empat istilah ini akan muncul berulang kali, jadi mari kita sepakati maknanya sejak awal.
| Istilah | Arti | Contoh di bab-bab berikutnya |
|---|---|---|
| SUT (System Under Test) | Code yang sedang diuji | Method PriceCalculator::total() |
| Fixture | Keadaan awal yang disiapkan sebelum test | Baris tabel posts hasil factory |
| Assertion | Pernyataan yang harus benar agar test lulus | assertSame(90000, $hasil) |
| Mock / Fake | Pengganti dependency eksternal agar test terisolasi | Queue::fake() pada chapter pengujian queue |
Struktur tests/ Bawaan Laravel #
Instalasi Laravel baru sudah membawa kerangka test yang bisa langsung dijalankan — perhatikan isinya pada aplikasi fresh:
tests/
├── Feature/
│ └── ExampleTest.php
├── Unit/
│ └── ExampleTest.php
└── TestCase.phpDua berkas ExampleTest.php adalah contoh hidup perbedaan dua lapisan piramida. Test di tests/Unit meng-extend PHPUnit\Framework\TestCase dan tidak mem-boot Laravel sama sekali. Test di tests/Feature meng-extend Tests\TestCase yang menyiapkan aplikasi utuh, sehingga bisa memanggil $this->get('/') layaknya request sungguhan. Berkas tests/TestCase.php adalah base class untuk seluruh test yang butuh framework.
Menjalankan seluruh suite cukup dengan satu perintah artisan:
php artisan testOutput yang Dihasilkan:
PASS Tests\Unit\ExampleTest
✓ that true is true
PASS Tests\Feature\ExampleTest
✓ the application returns a successful response 0.10s
Tests: 2 passed (2 assertions)
Duration: 0.18sDua test tersebut memang belum menguji apa pun yang bermakna, tetapi membuktikan pipeline-nya bekerja: PHPUnit menemukan test, menjalankannya dalam environment khusus, dan melaporkan hasilnya. Seluruh materi di section ini dibangun di atas pipeline itu. Sebelum menulis test pertama, kita perlu memahami konfigurasi yang membuatnya berjalan terisolasi — itu topik chapter berikutnya. Rujukan resmi tersedia di dokumentasi Testing Laravel .