Memastikan kualitas kode PHP: menulis unit test dengan PHPUnit dan Pest, memahami assertions, test structure, data provider, dan coverage, lalu debugging dengan Xdebug, var_dump/dd(), dan static analysis dengan PHPStan/Psalm sebagai jaring pengaman sebelum produksi.

Sampai episode 9, kita memverifikasi kode dengan cara manual: jalankan, lihat output, perbaiki. Itu tidak akan bertahan di proyek nyata. Episode ini mengajarkan kalian testing otomatis — cara menulis kode yang menguji kode — plus debugging untuk saat semuanya salah. Dua keterampilan yang paling membedakan junior dari senior.
Mengapa penting? Sebuah aplikasi produksi punya ratusan fungsi. Mengubah satu baris bisa merusak sepuluh hal lain yang tidak kalian ingat. Test otomatis menangkap regresi itu dalam hitungan detik, sementara static analysis menangkap kelas bug yang belum sempat dijalankan. Di episode 13-22, setiap kode yang kita tulis akan selalu disertai test.
Install dan siapkan:
composer require --dev phpunit/phpunitKonfigurasi di phpunit.xml:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="Unit">
<directory>tests/Unit</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory>src</directory>
</include>
</source>
</phpunit>Fungsi yang akan diuji:
namespace App;
class Price
{
public static function withTax(float $amount, float $rate = 0.11): float
{
return round($amount * (1 + $rate), 2);
}
}Unit test pertama:
namespace App\Tests;
use PHPUnit\Framework\TestCase;
use App\Price;
final class PriceTest extends TestCase
{
public function testTaxIsAdded(): void
{
self::assertSame(111.00, Price::withTax(100.00));
}
public function testTaxRateIsConfigurable(): void
{
self::assertSame(105.00, Price::withTax(100.00, 0.05));
}
}Jalankan:
vendor/bin/phpunitGunakan data provider untuk menguji banyak kasus dengan satu test, dan hitung coverage:
use PHPUnit\Framework\Attributes\DataProvider;
final class PriceTest extends TestCase
{
#[DataProvider('taxProvider')]
public function testTaxForVariousAmounts(float $amount, float $expected): void
{
self::assertSame($expected, Price::withTax($amount));
}
public static function taxProvider(): array
{
return [
"nol" => [0.00, 0.00],
"kecil" => [1.00, 1.11],
"ratusan" => [100.00, 111.00],
"negatif?" => [-50.00, -55.50],
];
}
}vendor/bin/phpunit --coverage-textCoverage 100% bukan tujuan akhir, tapi angka di bawah 80% untuk logika inti (harga, hak akses, validasi) adalah sinyal bahaya.
Pest dibangun di atas PHPUnit dengan sintaks yang lebih ekspresif:
composer require --dev pestphp/pest --with-all-dependencies
vendor/bin/pest --initTest Pest untuk fungsi yang sama:
use App\Price;
it("menambahkan pajak 11%", function () {
expect(Price::withTax(100.00))->toBe(111.00);
});
it("menghormati rate pajak custom", function (float $rate, float $expected) {
expect(Price::withTax(100.00, $rate))->toBe($expected);
})->with([
[0.05, 105.00],
[0.25, 125.00],
]);Pest unggul di readability — test dibaca seperti kalimat. Di episode 13+ kita akan memakai Pest karena sintaksnya pas untuk test Laravel/Slim.
Tip
Pilih satu: Pest untuk proyek baru (lebih ekspresif), PHPUnit untuk proyek lama (paling banyak dipakai di industri). Keduanya saling kompatibel — file test PHPUnit bisa berjalan di dalam Pest. Yang penting konsisten dalam satu proyek.
var_dump, dd(), dan LoggingDebugging paling sederhana:
var_dump($user); // cetak semua properti + tipe
print_r($user, true); // representasi lebih ringkas
// Laravel/TallStack: dd() = dump + die
// dd($request->all());Aturan praktis debugging:
var_dump di produksi — ganti dengan logging (error_log atau PSR-3 logger).var_dump cukup untuk masalah kecil. Untuk bug logika yang sulit, pakai Xdebug sebagai debugger interaktif (breakpoint, step over/into, inspeksi variabel live):
zend_extension=xdebug
xdebug.mode=debug
xdebug.start_with_request=yesDengan ekstensi PHP Debug di VS Code, kalian bisa menempatkan breakpoint di editor, lalu menekan Run and Debug — persis seperti debugging di bahasa lain. Xdebug juga bisa dipakai untuk profiling (episode 18) dengan xdebug.mode=profile.
Static analysis membaca seluruh kode tanpa menjalankannya — menangkap bug potensial lebih awal:
composer require --dev phpstan/phpstan
vendor/bin/phpstan analyse src --level=8Level 0-9 (PHPStan) atau tingkat serupa (Psalm). Semakin tinggi level, semakin ketat. Contoh yang dideteksi:
function ambilNama(array $user): string
{
return $user["nama"]; // PHPStan: offset "nama" mungkin tidak ada
}PHPStan akan meminta kalian menegaskan atau memvalidasi aksesnya — mencegah Undefined array key di produksi.
Warning
Static analysis bukan pengganti test — dan test bukan pengganti static analysis. Gabungan ketiganya (test + static analysis + code review) adalah standar industri. Di episode 19 kita menggabungkan semuanya ke pipeline CI.
assertSame/expect()->toBe wajib; test kosong hanya beri rasa aman palsu.var_dump tertinggal di kode — merusak output HTTP/JSON; gunakan logger di produksi.Inti yang harus dibawa pulang:
var_dump/dd(), bug sulit dengan Xdebug step debugger.Di episode 11 selanjutnya kita menghubungkan PHP ke dunia data: Working with Databases (PDO & Eloquent) — koneksi MySQL/PostgreSQL/SQLite, prepared statements yang aman dari SQL injection, transaksi, lalu ORM Eloquent dan Doctrine untuk produktivitas tinggi. Ini gerbang aplikasi nyata pertama kalian.