0Pricing
PHP Academy · Pelajaran

Pengujian Integrasi dan Fungsional

Uji cara komponen bekerja sama dalam kondisi nyata.

Pengujian Integrasi dan Fungsional adalah pelajaran PHP Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar PHP Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus PHP Academy mencakup 4 pelajaran total.

Di Luar Pengujian Unit

Pengujian unit membuktikan bahwa suatu kelas bekerja secara terisolasi dengan semua hal ditirukan. Namun, tiruan dapat menyesatkan—basis data, perute aplikasi, atau lapisan HTTP yang sebenarnya dapat berperilaku berbeda. Pengujian integrasi memverifikasi dua komponen nyata atau lebih yang dirangkai bersama; pengujian fungsional menjalankan aplikasi dari ujung ke ujung melalui titik masuk publiknya (permintaan HTTP atau perintah konsol). Dalam pelajaran ini, Anda akan memahami posisi keduanya dan menulisnya.

Piramida Pengujian

Kelompok pengujian yang sehat berbentuk seperti piramida:

  • Banyak pengujian unit — cepat, terisolasi, dan dijalankan terus-menerus.
  • Lebih sedikit pengujian integrasi — menggunakan basis data, antrean, dan tembolok nyata, sehingga lebih lambat.
  • Sedikit pengujian fungsional — menggunakan tumpukan lengkap, paling lambat, dan paling rapuh.

Membalik susunan ini hingga menjadi kelompok pengujian yang sebagian besar menjalankan aplikasi dari ujung ke ujung akan menghasilkan kelompok yang lambat dan tidak stabil. Jika memungkinkan, perbanyak cakupan pada lapisan bawah.

Integrasi: Repositori dengan Basis Data Nyata

Pengujian integrasi untuk repositori menggunakan koneksi basis data sungguhan—bukan tiruan—untuk menemukan galat SQL, skema, dan pemetaan. Gunakan basis data pengujian khusus (atau SQLite dalam memori yang cukup sesuai dengan dialek Anda) serta PDO sungguhan.

<?php
use PHPUnit\Framework\TestCase;

final class UserRepositoryTest extends TestCase
{
    private \PDO $pdo;

    protected function setUp(): void
    {
        $this->pdo = new \PDO('sqlite::memory:');
        $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
        $this->pdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT)');
    }

    public function test_persists_and_finds_a_user(): void
    {
        $repo = new UserRepository($this->pdo);
        $id = $repo->create('ada@example.com');
        self::assertSame('ada@example.com', $repo->find($id)->email);
    }
}

Isolasi: Pengembalian Transaksi

Pengujian integrasi tidak boleh membocorkan keadaan ke pengujian lain. Pola tercepat adalah membungkus setiap pengujian dalam transaksi lalu mengembalikannya di tearDown()—basis data kembali ke keadaan bersih tanpa perlu mengisi ulang data awal. (Pengosongan tabel menjadi pilihan cadangan ketika kode yang diuji melakukan commit atau menggunakan DDL.)

<?php
protected function setUp(): void
{
    $this->pdo = TestDb::connection();
    $this->pdo->beginTransaction();
}

protected function tearDown(): void
{
    $this->pdo->rollBack();   // undo everything this test did
}

Data Uji dan Pembuat Data

Pengujian memerlukan data. Hindari dump SQL raksasa yang rapuh; pilih pembuat data kecil yang hanya membuat baris yang diperlukan pengujian, dengan nilai bawaan yang masuk akal dan dapat Anda ubah untuk setiap kasus. Dengan begitu, tujuan setiap pengujian tetap jelas dan tahan terhadap perkembangan skema.

<?php
final class UserFactory
{
    public static function create(\PDO $pdo, array $overrides = []): int
    {
        $data = array_merge(['email' => 'user'.uniqid().'@test.dev'], $overrides);
        $stmt = $pdo->prepare('INSERT INTO users (email) VALUES (:email)');
        $stmt->execute($data);
        return (int) $pdo->lastInsertId();
    }
}

Fungsional: Mengakses Aplikasi Seperti Klien

Pengujian fungsional menjalankan kernel/perute aplikasi yang sebenarnya dengan permintaan simulasi dan memeriksa responsnya—kode status, tajuk, dan isi. WebTestCase milik Symfony serta pembantu pengujian HTTP Laravel melakukan hal ini tanpa menyalakan server web sungguhan. Berikut bentuknya dalam Symfony.

<?php
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

final class HealthControllerTest extends WebTestCase
{
    public function test_health_endpoint_returns_ok(): void
    {
        $client = static::createClient();
        $client->request('GET', '/health');

        self::assertResponseIsSuccessful();        // 2xx
        self::assertJson($client->getResponse()->getContent());
    }
}

Memeriksa Respons

Pengujian fungsional memeriksa perilaku yang dapat diamati pada batas aplikasi: status, struktur JSON, dan efek samping di basis data. Di bawah ini, POST membuat suatu sumber daya; kita memeriksa respons HTTP sekaligus memastikan bahwa catatan tersebut benar-benar tersimpan—membuktikan bahwa seluruh tumpukan bekerja sama.

<?php
public function test_creating_a_user_persists_it(): void
{
    $client = static::createClient();
    $client->request('POST', '/users', server: [
        'CONTENT_TYPE' => 'application/json',
    ], content: json_encode(['email' => 'ada@example.com']));

    self::assertResponseStatusCodeSame(201);

    $repo = static::getContainer()->get(UserRepository::class);
    self::assertNotNull($repo->findByEmail('ada@example.com'));
}

Menirukan Batas Eksternal Secara Selektif

Bahkan pengujian fungsional tidak boleh memanggil penyedia pembayaran nyata atau mengirim surel sungguhan. Gantilah hanya layanan eksternal yang paling luar—tukar layanan tersebut dalam wadah pengujian dengan implementasi tiruan atau dalam memori—sembari mempertahankan kode, perutean, dan basis data Anda sendiri agar tetap nyata. Dengan demikian, kesetiaan pengujian dari ujung ke ujung tetap terjaga tanpa panggilan jaringan yang tidak stabil.

<?php
public function test_checkout_charges_via_gateway(): void
{
    $client = static::createClient();
    // Replace the real gateway binding with an in-memory fake:
    static::getContainer()->set(PaymentGateway::class, new FakePaymentGateway());

    $client->request('POST', '/checkout', content: json_encode(['cart' => 1]));
    self::assertResponseIsSuccessful();
}

Kelompok Terpisah, Kecepatan Terpisah

Pisahkan phpunit.xml Anda ke dalam kelompok pengujian agar kelompok pengujian unit yang cepat berjalan setiap kali Anda menyimpan perubahan, sedangkan kelompok pengujian integrasi dan fungsional yang lambat berjalan sesuai kebutuhan atau di CI. Kelompokkan berdasarkan direktori dan pilih dengan --testsuite.

<phpunit>
  <testsuites>
    <testsuite name="unit">
      <directory>tests/Unit</directory>
    </testsuite>
    <testsuite name="integration">
      <directory>tests/Integration</directory>
    </testsuite>
    <testsuite name="functional">
      <directory>tests/Functional</directory>
    </testsuite>
  </testsuites>
</phpunit>

Determinisme Lebih Penting daripada Cakupan

Cara tercepat untuk kehilangan kepercayaan terhadap suatu kelompok pengujian adalah ketidakstabilan. Buat pengujian integrasi dan fungsional menjadi deterministik:

  • Bekukan waktu (masukkan jam) alih-alih memanggil time().
  • Tetapkan benih keacakan; hindari asersi yang bergantung pada urutan untuk kueri yang tidak diurutkan.
  • Atur ulang keadaan basis data pada setiap pengujian (pengembalian transaksi atau pengosongan tabel).
  • Jangan pernah bergantung pada urutan pelaksanaan pengujian.

Samakan Basis Data Pengujian dengan Produksi

SQLite dalam memori memang cepat, tetapi perbedaan dialek (sensitivitas huruf besar-kecil, fungsi JSON, penegakan kunci asing, dan tipe data) dapat menyembunyikan galat yang hanya muncul pada mesin nyata Anda. Untuk kode yang menggunakan SQL khusus mesin, jalankan pengujian integrasi pada mesin yang sama dengan produksi—biasanya menggunakan kontainer Docker sementara di CI—alih-alih pengganti yang sekadar praktis.

<?php
// Read connection from environment so CI points at a real Postgres/MySQL container
$dsn = getenv('TEST_DATABASE_URL') ?: 'sqlite::memory:';
$pdo = new \PDO($dsn);
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
// In CI, TEST_DATABASE_URL targets the same engine as production.

Pemeriksaan Cepat

Bagaimana seharusnya pengujian fungsional memperlakukan penyedia pembayaran pihak ketiga?

Ringkasan

Anda telah mempelajari cara menguji komponen secara bersama-sama:

  • Pengujian integrasi menggunakan basis data dan layanan nyata untuk menemukan hal-hal yang disembunyikan tiruan; isolasikan dengan pengembalian transaksi.
  • Pengujian fungsional menjalankan kernel nyata melalui permintaan simulasi dan memeriksa respons serta efek sampingnya.
  • Pembuat data membuat data minimum; tirukan hanya batas eksternal yang paling luar.
  • Pisahkan kelompok pengujian berdasarkan kecepatan dan jaga agar pengujian yang lebih lambat tetap deterministik.

Berikutnya: mengukur kualitas pengujian dengan pengujian mutasi.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Pengujian Integrasi dan Fungsional” gratis?

Ya — teks lengkap “Pengujian Integrasi dan Fungsional” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus PHP Academy, upgrade ke CoddyKit PRO. Kursus PHP Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Pengujian Integrasi dan Fungsional”?

Uji cara komponen bekerja sama dalam kondisi nyata. Kamu berlatih PHP Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai PHP Academy?

Tidak diperlukan pengalaman sebelumnya. PHP Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.

Berapa lama pelajaran “Pengujian Integrasi dan Fungsional” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran PHP Academy ini?

Ya. Setiap pelajaran PHP Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Alur Kerja Pengembangan Berbasis Pengujian
  2. Pemalsuan dan Penggantian dengan Mockery
  3. Pengujian Integrasi dan Fungsional
  4. Pengujian Mutasi dengan Infection
← Kembali ke PHP Academy