Pendahuluan — kenapa uji otomatis setelah Resource
Artikel ini adalah #68 (ini) di Seri 5: Laravel Lanjutan. Setelah bentuk jawaban JSON pinjam dirapikan lewat API Resource: Rapikan Bentuk JSON (#67), pertanyaan berikutnya muncul: bagaimana memastikan bentuk itu tetap benar setiap kali kode berubah?
Tanpa uji otomatis, kamu harus cek manual tiap hari: buka browser, panggil rute, lihat JSON, pastikan status_label ada dan anggota_id tidak bocor. Itu melelahkan dan mudah terlewat. Hari ini kita belajar Feature Test — uji otomatis yang memanggil rute API seperti klien sungguhan, lalu memeriksa status dan bentuk JSON dengan assertStatus, assertJson, dan assertJsonPath.
Awam: bayangkan petugas perpustakaan yang setiap malam menjalankan checklist otomatis pada slip pinjam: judul buku ada, nama anggota ada, status jelas, ID internal tidak bocor. Bukan cek manual satu per satu tiap pagi. Itu peran Feature Test setelah Resource merapikan JSON.
Prasyarat: sudah selesai API Resource: Rapikan Bentuk JSON (#67), paham fondasi Instal PHP, Composer & Proyek Laravel (#56) / Struktur Folder,
.env& Artisan Laravel (#57). Pakai Laravel 13+ — butuh PHP 8.3+.
Spesifikasi fitur — apa yang selesai hari ini?
Tiga hal ini yang kita kejar:
- Uji status HTTP — rute pinjam mengembalikan
200saat data ada, dicek denganassertStatus(200). - Uji field wajib —
id,judul_buku,nama_anggota,status,status_labelhadir di JSON. - Uji field tersembunyi —
anggota_idtidak ada di respons publik, dicek denganassertJsonMissingPathatau setara.
Awam: selesai artikel ini, kamu punya pola uji yang merawat bentuk JSON dari Resource — kalau besok ada yang tidak sengaja mengembalikan baris mentah, uji otomatis langsung gagal. Fokus kita PHPUnit-style Feature Test (bawaan Laravel). Pest ada sebagai alternatif singkat di akhir, tapi tidak wajib supaya awam tidak bingung.
Istilah — ringkas untuk uji otomatis
| Istilah | Arti awam | Catatan |
|---|---|---|
| Feature Test | Uji yang memanggil rute/API seperti pengguna sungguhan | File di tests\Feature |
assertStatus |
Perintah “status HTTP harus angka ini” | Misalnya assertStatus(200) |
assertJson |
Perintah “JSON harus punya potongan ini” | Cocok untuk field kecil |
assertJsonPath / assertJsonFragment |
Perintah “nilai di jalur JSON ini harus begini” atau “potongan JSON ini harus ada” | Misalnya data.0.status_label atau fragmen kecil field |
| Arrange-Act-Assert | Atur data -> jalankan aksi -> cek hasil | Dalam bahasa awam: atur-jalankan-cek |
| PHPUnit | Mesin uji bawaan Laravel untuk menjalankan Feature Test | php artisan test atau php vendor/bin/phpunit |
Urutan belajar kita: fungsi cek PHP dulu -> demo pass/fail -> baru cuplikan Feature Test Laravel. Kalau loncat langsung ke kelas uji tanpa paham apa yang dicek, assert sering ditulis asal-asalan.
Persiapan — alat yang kamu buka
Alat yang dipakai di artikel ini (fondasi dari Instal PHP, Composer & Proyek Laravel (#56) dan Struktur Folder, .env & Artisan Laravel (#57) — tidak ada unduhan Composer baru hari ini):
- Explorer — cek folder proyek
perpustakaan-api, lalu lihattests\Featuresertaapp\Http\Controllersdanapp\Http\Resourcesuntuk rute pinjam dan Resource. - Terminal — Laragon: menu Terminal · XAMPP: tombol Shell. Hindari CMD/PowerShell dari Start Menu kalau PATH PHP-mu belum rapi.
- Editor teks — Notepad / VS Code — untuk membuka file uji. Contoh:
notepad tests\Feature\PeminjamanResourceTest.php(atau nama serupa di foldertests\Feature). - Browser — opsional. Inti uji hari ini ada di terminal; browser berguna kalau kamu sudah menjalankan
php artisan servedan ingin bandingkan dengancurl.exe.
Awam: untuk artikel ini satu terminal sebenarnya cukup — jalankan php laravel_feature_test_api_demo.php di folder proyek. Untuk suite Laravel, di terminal yang sama jalankan php artisan test atau php vendor/bin/phpunit. Kalau php artisan serve dari artikel sebelumnya masih hidup, pakai terminal kedua untuk demo PHP dan perintah curl.exe saat ingin bandingkan JSON manual dengan hasil uji otomatis. Kalau butuh jendela kedua: Laragon — klik menu Terminal lagi · XAMPP — klik tombol Shell lagi, lalu cd ke folder proyek yang sama.
Buka terminal Laragon/Shell XAMPP, masuk ke folder proyek:
cd C:\laragon\www\perpustakaan-api
Di XAMPP biasanya: cd C:\xampp\htdocs\perpustakaan-api. Sesuaikan kalau foldermu beda.
Install-dari-nol: kalau php atau composer belum dikenali terminal, kembali dulu ke Instal PHP, Composer & Proyek Laravel (#56). Kalau struktur folder proyek masih membingungkan, ulangi Struktur Folder, .env & Artisan Laravel (#57).
Kenapa PHP biasa dulu?
Kalau langsung loncat ke kelas Feature Test di Laravel, pemula sering bingung: apa yang sebenarnya dicek? Maka kita mulai dari fungsi PHP biasa yang memeriksa array JSON — supaya perbedaan lolos vs gagal terlihat jelas sebelum dibungkus assertJsonPath.
<?php
// Mini: cek slip pinjam rapi vs bocor.
$jsonRapi = [
"id" => 10,
"judul_buku" => "Dasar PHP",
"nama_anggota" => "Budi",
"status" => "aktif",
"status_label" => "Sedang dipinjam",
];
$jsonBocor = [
"id" => 10,
"anggota_id" => 1,
"judul_buku" => "Dasar PHP",
"nama_anggota" => "Budi",
"status" => "aktif",
];
function cekSlipRapi(array $json): bool
{
$wajib = ["id", "judul_buku", "nama_anggota", "status", "status_label"];
foreach ($wajib as $field) {
if (! array_key_exists($field, $json)) {
return false;
}
}
return ! array_key_exists("anggota_id", $json);
}
echo cekSlipRapi($jsonRapi) ? "LOLOS" : "GAGAL", PHP_EOL;
echo cekSlipRapi($jsonBocor) ? "LOLOS" : "GAGAL", PHP_EOL;
Awam — cara menguji bagian ini: salin potongan di atas ke file misalnya uji-cek.php, lalu di terminal Laragon/XAMPP jalankan php uji-cek.php. Kalau muncul LOLOS lalu GAGAL, ide “uji bentuk JSON” sudah terlihat — yang rapi lolos, yang bocor anggota_id gagal.
Alur uji — atur, jalankan, cek
Gerakan yang benar selalu sama (Arrange-Act-Assert dalam bahasa awam: atur-jalankan-cek):
- Atur data — siapkan catatan pinjam di basis data uji atau array contoh.
- Jalankan aksi — panggil rute API (
getJsondi Laravel) seperti klien sungguhan. - Cek hasil — status HTTP benar, field wajib ada, field internal hilang.
- Ulangi saat kode berubah — satu perintah di terminal, bukan cek manual tiap pagi.
<?php
// Salin ke file misalnya uji-cek.php lalu jalankan: php uji-cek.php
$peminjamanRapi = [
"id" => 10,
"judul_buku" => "Dasar PHP",
"nama_anggota" => "Budi",
"status" => "aktif",
"status_label" => "Sedang dipinjam",
];
function assertFieldAda(array $json, string $field): bool
{
return array_key_exists($field, $json);
}
function assertFieldTidakAda(array $json, string $field): bool
{
return ! array_key_exists($field, $json);
}
$lolos = assertFieldAda($peminjamanRapi, "status_label")
&& assertFieldTidakAda($peminjamanRapi, "anggota_id");
echo $lolos ? "CEK LOLOS" : "CEK GAGAL", PHP_EOL;
echo json_encode($peminjamanRapi, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), PHP_EOL;
Awam — cara menguji bagian ini: salin potongan di atas ke uji-cek.php, lalu di terminal jalankan php uji-cek.php. Kalau muncul CEK LOLOS dan JSON tanpa anggota_id, fondasi assert sudah sehat. Ini versi PHP murni dari apa yang nanti ditulis sebagai assertJsonPath di Laravel.
Laravel — cuplikan Feature Test (bukan file mandiri)
Di proyek Laravel, uji ditulis di folder tests\Feature. Cuplikan berikut memanggil rute pinjam dan memeriksa bentuk JSON dari Resource.
<?php
// Cuplikan Laravel (bukan file mandiri)
// tests/Feature/PeminjamanResourceTest.php
namespace Tests\Feature;
use App\Models\Peminjaman;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class PeminjamanResourceTest extends TestCase
{
use RefreshDatabase;
public function test_peminjaman_json_rapi(): void
{
$peminjaman = Peminjaman::factory()->create([
"status" => "aktif",
]);
$response = $this->getJson("/api/peminjaman/{$peminjaman->id}");
$response->assertStatus(200)
->assertJsonPath("data.id", $peminjaman->id)
->assertJsonPath("data.judul_buku", $peminjaman->buku->judul)
->assertJsonPath("data.nama_anggota", $peminjaman->anggota->nama)
->assertJsonPath("data.status", "aktif")
->assertJsonPath("data.status_label", "Sedang dipinjam")
->assertJsonMissingPath("data.anggota_id");
}
}
Awam: getJson = panggil rute seperti klien API. assertStatus(200) = status HTTP harus sukses. assertJsonPath = nilai di jalur JSON harus cocok. assertJsonMissingPath = field internal tidak boleh ada. Cuplikan ini bukan file mandiri — tempel ke proyek kalau rute dan factory pinjam sudah ada.
Jalankan suite uji di terminal yang sama:
php artisan test
php vendor/bin/phpunit --filter test_peminjaman_json_rapi
Kalau php artisan serve sudah jalan di terminal pertama, bandingkan manual di terminal kedua dengan curl.exe (opsional):
curl.exe "http://127.0.0.1:8000/api/peminjaman/10"
Awam: curl.exe membantu melihat JSON dengan mata — tapi yang mengunci bentuk setiap hari adalah php artisan test, bukan cek manual. Kalau muncul 404, rute pinjam mungkin belum dipasang — itu wajar; fokus dulu ke demo PHP di atas. Kalau php artisan test gagal karena status 404 atau factory belum ada, rute/Resource belum siap — bukan berarti ide Feature Test salah. Kalau uji gagal padahal rute hidup, biasanya field hilang atau anggota_id bocor kembali.
Catatan singkat: Pest adalah alternatif sintaks uji yang lebih ringkas; Laravel mendukungnya, tapi artikel ini fokus PHPUnit karena itu bawaan dan dokumentasi resmi paling mudah diikuti awam.
Pola Dasar — uji yang merawat JSON
-
1
Atur data uji
Siapkan catatan pinjam — factory atau seeder di basis data uji. -
2
Panggil rute API
getJsonke/api/peminjaman/{id}seperti klien sungguhan. -
3
Cek status HTTP
assertStatus(200)— rute hidup dan tidak error. -
4
Cek field wajib
assertJsonPathuntukid,judul_buku,nama_anggota,status,status_label. -
5
Cek field tersembunyi
assertJsonMissingPath("data.anggota_id")— ID internal tidak bocor. -
6
Jalankan berulang
php artisan testsetiap kode berubah — checklist otomatis, bukan cek manual.
Kode lengkap — demo mandiri
Simpan sebagai laravel_feature_test_api_demo.php, lalu jalankan php laravel_feature_test_api_demo.php:
<?php
declare(strict_types=1);
$peminjamanRapi = [
"id" => 10,
"judul_buku" => "Dasar PHP",
"nama_anggota" => "Budi",
"status" => "aktif",
"status_label" => "Sedang dipinjam",
];
$peminjamanBocor = [
"id" => 11,
"anggota_id" => 2,
"judul_buku" => "Belajar Laravel",
"nama_anggota" => "Siti",
"status" => "aktif",
];
function cekBentukJson(array $json): array
{
$wajib = ["id", "judul_buku", "nama_anggota", "status", "status_label"];
$gagal = [];
foreach ($wajib as $field) {
if (! array_key_exists($field, $json)) {
$gagal[] = "field hilang: {$field}";
}
}
if (array_key_exists("anggota_id", $json)) {
$gagal[] = "anggota_id tidak boleh ada";
}
return ["lolos" => $gagal === [], "gagal" => $gagal];
}
function demo(string $judul, array $json): void
{
echo "=== {$judul} ===", PHP_EOL;
$hasil = cekBentukJson($json);
echo $hasil["lolos"] ? "LOLOS" : "GAGAL", PHP_EOL;
if ($hasil["gagal"] !== []) {
echo implode(", ", $hasil["gagal"]), PHP_EOL;
}
echo json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), PHP_EOL, PHP_EOL;
}
demo("Slip rapi — harus lolos", $peminjamanRapi);
demo("Slip bocor — harus gagal", $peminjamanBocor);
demo("Tanpa status_label — harus gagal", [
"id" => 12,
"judul_buku" => "PHP Lanjut",
"nama_anggota" => "Ani",
"status" => "kembali",
]);
Awam — cara menguji bagian ini: simpan file sebagai laravel_feature_test_api_demo.php di folder proyek, lalu di terminal Laragon/XAMPP jalankan php laravel_feature_test_api_demo.php. Harusnya muncul satu LOLOS lalu dua GAGAL. Fungsi cekBentukJson adalah inti logika; demo(...) hanya membungkus output agar mudah dibaca di terminal — mirip apa yang dilakukan assertJsonPath di Laravel.
Kesalahan umum
| Gejala | Penyebab tipikal | Perbaikan awam |
|---|---|---|
| Uji lolos tapi JSON di browser salah | Uji tidak memanggil rute yang sama dengan produksi | Pastikan getJson ke URL yang benar |
anggota_id bocor tapi uji tidak gagal |
Lupa assert field tersembunyi | Tambah assertJsonMissingPath("data.anggota_id") |
| Uji gagal padahal Resource benar | Data uji tidak disiapkan (factory/seeder kosong) | Atur data dulu di langkah Arrange |
assertJsonPath selalu gagal |
Jalur JSON salah — misalnya lupa awalan data. |
Cek respons mentah dengan curl.exe atau dump() |
| Hanya cek status, tidak cek isi | Hanya assertStatus(200) tanpa assert JSON |
Tambah assert untuk setiap field wajib dari Resource |
php artisan test tidak dikenali |
Terminal bukan dari Laragon/XAMPP | Buka Terminal Laragon atau Shell XAMPP, cd ke proyek |
Latihan singkat
- Ubah demo: tambah assert bahwa
status_labeluntuk statuskembaliharus “Sudah kembali”. - Jelaskan ke teman: beda cek manual tiap pagi vs checklist otomatis setiap malam — pakai analogi petugas perpustakaan.
- Tulis satu kalimat: kenapa
assertJsonMissingPathpenting setelah Resource menyembunyikananggota_id.
FAQ singkat
Apakah Feature Test menggantikan Resource?
Tidak. Resource dari API Resource: Rapikan Bentuk JSON (#67) merapikan bentuk jawaban. Feature Test memastikan bentuk itu tetap benar setiap kode berubah.
Haruskah pakai Pest, bukan PHPUnit?
Tidak wajib. PHPUnit adalah bawaan Laravel dan fokus artikel ini. Pest opsional kalau kamu sudah nyaman — polanya sama: atur, jalankan, cek.
Tool apa yang dibuka dulu?
Explorer untuk memastikan folder proyek benar (tests\Feature + Controllers/Resources), satu terminal untuk demo PHP, editor untuk file uji. Kalau serve hidup, terminal kedua untuk curl.exe bandingan opsional.
Potongan sintaks diuji di mana?
Langkah tengah (fungsi cek array) salin ke uji-cek.php, lalu jalankan php uji-cek.php. Demo lengkap diuji dengan php laravel_feature_test_api_demo.php. Cuplikan Laravel ditempel ke tests\Feature\PeminjamanResourceTest.php; jalankan suite dengan php artisan test atau php vendor/bin/phpunit.
Ke mana setelah ini?
Berikutnya alami: Rate Limiting API (#69) — batasi spam request ke API perpustakaan mini.
Kesimpulan
Kamu sudah mengunci bentuk jawaban JSON dari Resource dengan uji otomatis: fungsi cek PHP dulu di uji-cek.php, demo pass/fail di laravel_feature_test_api_demo.php, lalu cuplikan Feature Test Laravel dengan assertStatus, assertJsonPath, dan assertJsonMissingPath. Checklist otomatis setiap malam — bukan cek manual tiap pagi.
Seri 5 progress: langkah #68 (ini) · 5/7 Laravel Lanjutan · prasyarat: API Resource: Rapikan Bentuk JSON (#67) LIVE. Berikutnya: Rate Limiting API (#69).