← Semua pembelajaran / Laravel Nol → Enterprise
Fase 6 · Testing & Kualitas Kode

Pest

Pest bukan mesin tes baru — ia berjalan di atas PHPUnit. Yang ditawarkannya adalah sintaks yang menghilangkan boilerplate kelas, plus beberapa alat yang benar-benar berguna seperti dataset dan uji arsitektur.

Sumber asli pestphp.com Resmi Rangkuman ~5 menit baca

Intisari

  • Tes ditulis sebagai fungsi it() atau test(), bukan method di dalam kelas.
  • Semua assertion PHPUnit tetap tersedia — migrasi bisa bertahap, keduanya boleh hidup berdampingan.
  • Dataset membuat satu tes berjalan untuk banyak masukan tanpa perulangan.
  • Arch test menegakkan aturan struktur kode: "tidak ada dd() di app/".
  • pest --parallel dan --dirty (hanya berkas yang berubah) mempercepat siklus kerja.

Bentuknya

composer require pestphp/pest --dev
php artisan pest:install
// tests/Feature/ArtikelTest.php
use function Pest\Laravel\{get, post, actingAs};

it('menampilkan artikel yang sudah terbit', function () {
    $artikel = Artikel::factory()->terbit()->create(['judul' => 'Kabar Pagi']);

    get(route('artikel.show', $artikel))
        ->assertOk()
        ->assertSee('Kabar Pagi');
});

it('menolak kontributor yang mencoba menerbitkan', function () {
    $artikel = Artikel::factory()->draf()->create();

    actingAs(User::factory()->kontributor()->create())
        ->post(route('artikel.terbit', $artikel))
        ->assertForbidden();
});
// tests/Pest.php — berlaku untuk seluruh folder
pest()->extend(Tests\TestCase::class)
    ->use(Illuminate\Foundation\Testing\RefreshDatabase::class)
    ->in('Feature');

Nama tes jadi kalimat. it('menolak kontributor yang mencoba menerbitkan') terbaca sebagai spesifikasi. Saat sebuah tes gagal, keluaran CI langsung memberi tahu aturan bisnis mana yang rusak, bukan sekadar nama method yang harus ditebak artinya.

Dataset

it('menolak slug yang tidak valid', function (string $slug) {
    actingAs(editor())
        ->post(route('artikel.store'), ['judul' => 'X', 'slug' => $slug])
        ->assertSessionHasErrors('slug');
})->with([
    'spasi'          => 'judul artikel',
    'karakter aneh'  => 'judul@artikel',
    'kosong'         => '',
    'terlalu panjang' => str_repeat('a', 300),
]);

Empat kasus, satu tes, dan setiap kasus dilaporkan terpisah saat gagal. Ini bentuk yang jauh lebih jujur daripada satu tes berisi foreach — yang berhenti di kegagalan pertama dan menyembunyikan sisanya.

Hook dan helper bersama

beforeEach(function () {
    $this->editor = User::factory()->editor()->create();
});

// tests/Pest.php — helper yang bisa dipakai semua tes
function editor(): User
{
    return User::factory()->editor()->create();
}

Uji arsitektur

// tests/Feature/ArchTest.php
arch('tidak ada sisa debugging')
    ->expect(['dd', 'dump', 'ray', 'var_dump', 'die'])
    ->not->toBeUsed();

arch('controller tidak boleh menyentuh database langsung')
    ->expect('App\Http\Controllers')
    ->not->toUse('Illuminate\Support\Facades\DB');

arch('model tinggal di tempatnya')
    ->expect('App\Models')
    ->toBeClasses()
    ->toExtend('Illuminate\Database\Eloquent\Model');

arch('semua enum berbasis string')
    ->expect('App\Enums')
    ->toBeStringBackedEnums();

arch()->preset()->security();     // periksa fungsi berbahaya: eval, extract, md5, …

Uji arsitektur menegakkan kesepakatan tim tanpa perlu review manual. Aturan seperti "controller tidak boleh memanggil DB langsung" biasanya hidup sebagai kebiasaan yang perlahan luntur. Sebagai tes, ia jadi gerbang yang tidak bisa dilewati diam-diam — dan pesan gagalnya menyebutkan berkas persisnya.

Perintah harian

./vendor/bin/pest
./vendor/bin/pest --parallel
./vendor/bin/pest --dirty              # hanya berkas yang berubah menurut git
./vendor/bin/pest --filter=artikel
./vendor/bin/pest --coverage --min=70
./vendor/bin/pest --profile            # sepuluh tes paling lambat

--profile layak dijalankan sesekali. Suite yang mulai terasa lambat biasanya bukan lambat merata: dua atau tiga tes membuat ratusan baris data atau menunggu sesuatu yang lupa dipalsukan. Memperbaiki tiga tes teratas sering memangkas separuh waktu total.

Migrasi bertahap dari PHPUnit

Pest menjalankan kelas PHPUnit apa adanya. Kamu bisa memasangnya hari ini, menulis tes baru dengan gaya Pest, dan membiarkan tes lama tetap berupa kelas. Tidak ada tekanan untuk mengonversi semuanya — dan mengonversi tes yang sedang berjalan baik-baik saja adalah pekerjaan yang tidak menambah nilai apa pun.

Latihan: konversi satu berkas tes dari kelas PHPUnit ke gaya Pest, lalu tambahkan satu dataset berisi empat slug tidak valid. Terakhir, tambahkan arch('tidak ada sisa debugging') dan buktikan ia gagal dengan menaruh satu dd() di controller.

Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.