Smoke test rilis di CodeIgniter 4 bertujuan menjawab satu pertanyaan sederhana setelah deploy: apakah alur bisnis paling penting masih hidup dan bisa dipakai? Jika login gagal, endpoint create order error, atau webhook callback tidak lagi diterima, maka aplikasi secara praktis belum layak dirilis walaupun unit test lulus.

Masalah umum di banyak tim adalah test sudah banyak, tetapi tidak ada lapisan pemeriksaan cepat yang benar-benar merepresentasikan risiko produksi setelah deploy. Artikel ini membahas cara menyusun smoke test pasca-deploy di CodeIgniter 4 untuk mencegah regresi pada endpoint kritis, termasuk prioritas endpoint, data uji yang stabil, penggunaan stub/fake untuk dependency eksternal, dan aturan gagal yang harus memblokir rilis.

Mengapa smoke test rilis berbeda dari unit test dan integration test

Ketiga jenis test ini punya tujuan berbeda, dan justru efektif bila dipakai bersama:

  • Unit test memverifikasi logika kecil secara terisolasi, misalnya validasi payload, perhitungan status order, atau pembentukan signature webhook.
  • Integration test memverifikasi interaksi antar komponen internal, misalnya controller ke service ke database, atau service ke repository.
  • Smoke test HTTP memverifikasi endpoint yang benar-benar tersedia dan berfungsi setelah aplikasi dijalankan dalam lingkungan target deploy.

Kesalahan yang sering terjadi adalah menjadikan smoke test terlalu dalam. Smoke test bukan pengganti seluruh regresi suite. Ia harus cepat, sempit, dan berorientasi risiko. Tujuannya bukan menguji semua cabang logika, melainkan memastikan sistem tidak rusak pada jalur yang paling mahal jika gagal.

Menentukan endpoint kritis yang wajib masuk smoke test

Jangan mulai dari semua endpoint. Mulailah dari endpoint yang bila gagal akan menghentikan operasional utama, merusak integrasi penting, atau menyebabkan insiden bisnis langsung. Untuk banyak aplikasi, empat contoh yang realistis adalah:

  • Health check: memastikan aplikasi hidup dan dependensi minimum tersedia.
  • Login: memastikan autentikasi masih bekerja.
  • Create order: memastikan alur transaksi inti belum regresi.
  • Callback webhook: memastikan sistem masih dapat menerima notifikasi dari pihak ketiga.

Cara memilih alur bisnis inti

Gunakan kriteria sederhana berikut untuk menyusun daftar prioritas:

  1. Dampak bisnis: jika endpoint gagal, apakah pengguna tidak bisa menyelesaikan tujuan utama?
  2. Frekuensi penggunaan: apakah endpoint dipakai di hampir semua sesi pengguna?
  3. Risiko perubahan: apakah endpoint sering tersentuh saat pengembangan?
  4. Ketergantungan lintas sistem: apakah endpoint mengandalkan database, cache, auth, queue, atau service eksternal?
  5. Sulit dideteksi secara manual: apakah error baru terlihat setelah beberapa langkah atau notifikasi terlambat?

Dari sini, buat pengelompokan prioritas yang jelas.

Contoh pengelompokan prioritas

  • P0 - bloker rilis: health check, login, create order.
  • P1 - sangat penting: webhook callback, refresh token, ambil detail order.
  • P2 - non-kritis saat rilis awal: laporan, endpoint admin sekunder, fitur ekspor.

Untuk tim kecil, mulai dari 3 sampai 5 test P0 sudah jauh lebih berguna daripada puluhan test yang rapuh.

Struktur smoke test yang praktis di CodeIgniter 4

Di CodeIgniter 4, Anda bisa memanfaatkan test HTTP berbasis framework untuk memanggil route dan memverifikasi status respons, header, atau potongan isi respons. Untuk smoke test rilis, susun test berdasarkan domain, bukan berdasarkan jenis file semata. Tujuannya agar pembacaan suite lebih dekat ke alur bisnis.

Contoh struktur direktori

tests/
  smoke/
    Release/
      HealthCheckSmokeTest.php
      AuthSmokeTest.php
      OrderSmokeTest.php
      WebhookSmokeTest.php
  integration/
    Auth/
    Order/
  unit/
    Services/
    Validators/

Pemisahan ini membantu pipeline mengeksekusi suite yang berbeda untuk tujuan berbeda. Smoke test harus bisa dijalankan cepat dan independen dari suite unit atau integration yang lebih luas.

Contoh cakupan minimal per endpoint

1. Health check

  • Status HTTP sesuai ekspektasi.
  • Payload menandakan aplikasi siap menerima trafik.
  • Jika health check memeriksa dependensi, pastikan hanya dependensi minimum yang benar-benar dibutuhkan untuk melayani request inti.

2. Login

  • Request dengan kredensial uji valid menghasilkan respons sukses.
  • Token atau sesi benar-benar terbentuk, bukan hanya status 200.
  • Respons error untuk kredensial salah tidak perlu diuji di smoke test; itu lebih cocok di integration atau unit test.

3. Create order

  • Payload valid menghasilkan order baru.
  • Respons mengandung identifier order atau status yang dapat diverifikasi.
  • Efek samping penting diverifikasi secara minimum, misalnya record tersimpan atau event internal terbentuk.

4. Callback webhook

  • Endpoint menerima request dengan header/signature yang valid.
  • Respons acknowledgment benar agar pengirim tidak melakukan retry terus-menerus.
  • Dependency ke provider eksternal tidak perlu dipanggil balik dalam smoke test.

Contoh implementasi smoke test HTTP di CodeIgniter 4

Contoh berikut bersifat praktis: fokus pada verifikasi minimum yang bernilai tinggi, bukan pada semua skenario.

Smoke test health check

<?php

namespace Tests\Smoke\Release;

use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FeatureTestTrait;

class HealthCheckSmokeTest extends CIUnitTestCase
{
    use FeatureTestTrait;

    public function testHealthCheckEndpointIsUp(): void
    {
        $result = $this->get('/health');

        $result->assertStatus(200);
        $result->assertJSONFragment(['status' => 'ok']);
    }
}

Test ini sengaja pendek. Health check tidak perlu memverifikasi seluruh subsistem, karena jika terlalu banyak dependensi dimasukkan, endpoint ini justru mudah gagal oleh komponen yang sebenarnya tidak kritis untuk menerima trafik awal.

Smoke test login

<?php

namespace Tests\Smoke\Release;

use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FeatureTestTrait;

class AuthSmokeTest extends CIUnitTestCase
{
    use FeatureTestTrait;

    public function testUserCanLoginWithReleaseTestAccount(): void
    {
        $payload = [
            'email'    => '[email protected]',
            'password' => 'password-yang-dikelola-aman'
        ];

        $result = $this->post('/api/login', $payload);

        $result->assertStatus(200);
        $result->assertJSONFragment(['message' => 'login success']);
    }
}

Di lingkungan nyata, jangan simpan kredensial sensitif langsung di source code. Untuk pipeline, ambil dari environment variable atau secret manager. Tujuan test ini adalah memverifikasi rantai autentikasi penting masih berfungsi: route, controller, validasi, user provider, dan mekanisme session/token.

Smoke test create order

<?php

namespace Tests\Smoke\Release;

use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FeatureTestTrait;

class OrderSmokeTest extends CIUnitTestCase
{
    use FeatureTestTrait;

    public function testCreateOrderWithStablePayload(): void
    {
        $payload = [
            'customer_id' => 'cust-smoke-001',
            'items' => [
                ['sku' => 'SKU-DEMO-001', 'qty' => 1]
            ],
            'reference' => 'smoke-release-001'
        ];

        $result = $this->withHeaders([
            'Authorization' => 'Bearer test-token'
        ])->post('/api/orders', $payload);

        $result->assertStatus(201);
        $result->assertJSONFragment(['status' => 'created']);
    }
}

Poin penting di sini bukan hanya status 201, tetapi penggunaan payload yang stabil dan dapat diprediksi. Jika order creation bergantung pada stok, promo dinamis, atau harga realtime, Anda perlu mengisolasi atau mengendalikan faktor tersebut agar smoke test tidak flakey.

Smoke test webhook callback

<?php

namespace Tests\Smoke\Release;

use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\FeatureTestTrait;

class WebhookSmokeTest extends CIUnitTestCase
{
    use FeatureTestTrait;

    public function testWebhookCallbackAcceptedWithValidSignature(): void
    {
        $payload = [
            'event' => 'payment.paid',
            'order_id' => 'order-smoke-001'
        ];

        $signature = hash_hmac('sha256', json_encode($payload), 'test-webhook-secret');

        $result = $this->withHeaders([
            'X-Signature' => $signature,
            'Content-Type' => 'application/json'
        ])->post('/webhooks/payment', $payload);

        $result->assertStatus(200);
    }
}

Pada endpoint webhook, verifikasi paling bernilai adalah endpoint bisa menerima callback valid dan memberi acknowledgment yang benar. Anda tidak perlu memanggil provider pembayaran sungguhan hanya untuk smoke test pasca-deploy.

Data uji yang stabil: kunci agar smoke test tidak flakey

Smoke test yang sering merah karena data tidak stabil akan segera diabaikan tim. Karena itu, desain data uji harus dipikirkan sejak awal.

Prinsip data uji stabil

  • Gunakan entitas khusus smoke test, misalnya user, customer, dan SKU yang memang disediakan untuk pengujian.
  • Hindari data yang berubah oleh proses bisnis normal, seperti stok produk live atau akun pengguna biasa.
  • Buat payload idempoten bila memungkinkan, misalnya reference unik yang memiliki pola terkontrol.
  • Siapkan reset atau cleanup bila endpoint membuat data baru secara permanen.
  • Jangan bergantung pada waktu lokal tanpa kontrol, terutama untuk token expiry, jadwal, dan signature berbasis timestamp.

Pendekatan yang aman untuk create order

Jika order test akan selalu membuat data baru, tentukan salah satu strategi berikut:

  1. Menggunakan tenant atau namespace khusus untuk data smoke test.
  2. Menghapus data hasil test setelah verifikasi selesai.
  3. Membuat endpoint create order mengenali mode sandbox di environment non-produksi.

Trade-off-nya jelas: cleanup menambah kompleksitas, sedangkan sandbox menambah cabang konfigurasi. Untuk tim kecil, biasanya strategi tenant/data khusus lebih mudah dikelola.

Isolasi dependency eksternal dengan stub dan fake

Smoke test rilis sebaiknya menguji kesiapan aplikasi Anda, bukan kestabilan semua vendor eksternal. Jika create order memicu email, queue, payment gateway, atau callback ke service lain, jangan biarkan semua itu menjadi syarat lulus smoke test kecuali benar-benar bagian dari sinyal rilis yang ingin Anda blokir.

Apa yang perlu di-stub atau di-fake

  • Klien HTTP ke service pihak ketiga.
  • Pengiriman email atau notifikasi.
  • Queue publisher atau worker asynchronous.
  • Pembacaan file atau storage eksternal jika bukan inti alur smoke test.

Kenapa stub/fake penting

Tanpa isolasi, Anda akan mendapatkan dua masalah: test menjadi lambat dan hasilnya tidak deterministik. Misalnya, create order lolos secara internal tetapi gagal hanya karena service notifikasi sedang lambat. Itu bisa jadi masalah observabilitas, tetapi belum tentu alasan untuk memblokir rilis API inti.

Pola desain yang memudahkan penggantian dependency

Jika controller atau service Anda bergantung pada antarmuka, pengujian akan lebih mudah. Contohnya, alih-alih memanggil HTTP client langsung di controller, bungkus akses itu di service atau interface seperti PaymentNotifierInterface. Pada environment test, injeksikan implementasi fake yang mengembalikan respons terkontrol.

Prinsip praktisnya: smoke test harus gagal karena aplikasi Anda rusak, bukan karena dunia luar sedang tidak stabil.

Menyeimbangkan unit test, integration test, dan smoke test HTTP

Satu suite yang terlalu berat akan sulit dipelihara. Lebih efektif bila setiap lapisan menguji hal yang tepat.

Apa yang sebaiknya diuji di unit test

  • Validator login dan aturan payload.
  • Pembentukan signature webhook.
  • Logika status order.
  • Mapper respons dan transformasi data.

Apa yang sebaiknya diuji di integration test

  • Controller login berinteraksi dengan model/repository.
  • Create order menyimpan data ke database dan memicu event internal.
  • Webhook callback memperbarui status order dengan benar.

Apa yang sebaiknya diuji di smoke test HTTP

  • Endpoint penting dapat diakses setelah deploy.
  • Request minimum valid menghasilkan respons sukses.
  • Autentikasi, routing, middleware/filter, dan dependency inti berjalan bersama.

Aturan mudahnya: semakin detail cabang logika, semakin cocok di unit/integration; semakin fokus pada kesiapan rilis, semakin cocok di smoke test.

Checklist minimum sebelum rilis penuh

Berikut daftar cek minimum yang realistis untuk release gate:

  1. Health check lulus dan menunjukkan aplikasi siap.
  2. Login lulus dengan akun uji yang valid.
  3. Create order lulus dengan payload stabil.
  4. Webhook callback lulus dengan signature valid.
  5. Tidak ada error 5xx pada endpoint P0.
  6. Migration/schema yang dibutuhkan sudah sesuai dengan aplikasi yang dideploy.
  7. Konfigurasi environment penting terbaca, misalnya secret auth dan base URL internal yang dibutuhkan.

Tidak semua item harus divalidasi lewat satu test suite. Beberapa bisa divalidasi lewat health check, observability, atau langkah verifikasi deployment. Yang penting, daftar ini eksplisit dan bisa diotomasi semaksimal mungkin.

Integrasi smoke test ke pipeline CI/CD

Smoke test rilis paling berguna bila diletakkan setelah deploy ke environment target dan sebelum trafik penuh dibuka. Ini berlaku baik untuk staging maupun produksi dengan strategi rollout bertahap.

Urutan pipeline yang umum

  1. Build artifact.
  2. Jalankan unit test dan integration test.
  3. Deploy ke staging atau slot/canary.
  4. Jalankan smoke test HTTP terhadap hasil deploy.
  5. Jika lulus, lanjutkan switch traffic atau promote release.
  6. Jika gagal, rollback atau hentikan rollout.

Contoh alur command sederhana

# sebelum deploy
php vendor/bin/phpunit --testsuite unit
php vendor/bin/phpunit --testsuite integration

# setelah deploy ke target
php vendor/bin/phpunit --testsuite smoke

Nama testsuite dapat disesuaikan dengan konfigurasi proyek Anda. Yang penting adalah pemisahan yang jelas agar smoke test bisa dijalankan cepat tanpa menunggu seluruh regresi suite.

Kapan harus memblokir rilis

Berikut sinyal gagal yang seharusnya menghentikan rilis:

  • Endpoint P0 mengembalikan status 5xx.
  • Login tidak bisa menghasilkan sesi/token yang valid.
  • Create order gagal membuat transaksi minimum.
  • Webhook callback tidak menerima signature valid atau tidak mengembalikan acknowledgment yang benar.
  • Health check menunjukkan aplikasi tidak siap melayani request.

Sebaliknya, sinyal seperti notifikasi non-kritis terlambat, dashboard admin sekunder error, atau metrik observability tambahan tidak muncul belum tentu harus menjadi blocker, tergantung kebijakan risiko tim.

Kesalahan umum yang membuat smoke test tidak berguna

Terlalu banyak skenario

Smoke test yang melebar menjadi suite regresi mini akan lambat, rapuh, dan sulit dibaca. Pilih jalur emas saja.

Hanya memeriksa status 200

Status 200 belum berarti login benar-benar berhasil atau order benar-benar dibuat. Verifikasi indikator bisnis minimum, misalnya token ada, status created muncul, atau identifier order dikembalikan.

Memakai data live yang berubah-ubah

Ini sumber flaky test paling umum. Gunakan data khusus uji yang tidak dipakai pengguna nyata.

Bergantung pada service eksternal tanpa kontrol

Bila semua dependency eksternal diwajibkan hidup, smoke test akan sering gagal karena faktor di luar aplikasi Anda.

Menjalankan smoke test hanya sebelum deploy

Tujuan smoke test rilis adalah memvalidasi hasil deploy, sehingga ia harus dijalankan terhadap environment yang sudah menerima artifact dan konfigurasi aktual.

Tidak ada aturan rollback yang jelas

Jika smoke test gagal tetapi tim tetap lanjut rilis karena tidak ada prosedur baku, maka suite itu hanya menjadi formalitas.

Tips debugging saat smoke test gagal

  • Bandingkan environment variable antara build sebelumnya dan release sekarang.
  • Cek route dan filter bila endpoint tiba-tiba 404, 401, atau 403.
  • Verifikasi migration/database schema bila create order atau login rusak setelah perubahan tabel.
  • Periksa log aplikasi untuk exception sebenarnya, bukan hanya status HTTP.
  • Pastikan data uji masih valid, misalnya user belum dinonaktifkan atau secret webhook tidak berubah.
  • Isolasi dependency eksternal untuk memastikan akar masalah ada di aplikasi, bukan vendor luar.

Checklist implementasi bertahap untuk tim kecil

Tim kecil tidak perlu membangun sistem testing yang besar sekaligus. Implementasikan bertahap agar manfaatnya cepat terasa.

Tahap 1: mulai dari 3 endpoint P0

  1. Buat smoke test untuk /health.
  2. Tambahkan smoke test untuk login.
  3. Tambahkan smoke test untuk create order dengan data uji stabil.

Target tahap ini: punya release gate minimum yang benar-benar berguna.

Tahap 2: stabilkan data dan dependency

  1. Sediakan akun dan data fixture khusus smoke test.
  2. Pisahkan dependency eksternal lewat interface/service wrapper.
  3. Tambahkan fake/stub untuk komponen non-kritis.

Target tahap ini: mengurangi flaky failure.

Tahap 3: tambahkan webhook callback

  1. Siapkan payload dan signature yang terkontrol.
  2. Verifikasi acknowledgment minimum.
  3. Pastikan test tidak memanggil provider eksternal sungguhan.

Target tahap ini: menutup risiko integrasi penting yang sering terlewat.

Tahap 4: masukkan ke CI/CD sebagai release gate

  1. Jalankan suite smoke setelah deploy.
  2. Hentikan promosi rilis jika ada P0 gagal.
  3. Dokumentasikan langkah rollback dan owner penanganannya.

Target tahap ini: smoke test menjadi kontrol operasional, bukan hanya test lokal.

Penutup

CodeIgniter 4 smoke test rilis yang efektif tidak harus banyak. Yang penting adalah memilih endpoint yang benar-benar kritis, menggunakan data uji yang stabil, mengisolasi dependency eksternal, dan menjalankannya setelah deploy sebagai bagian dari release gate. Untuk kebanyakan aplikasi, health check, login, create order, dan webhook callback sudah cukup menjadi fondasi awal yang kuat.

Jika Anda harus memilih prioritas, dahulukan jalur bisnis yang kegagalannya paling cepat terasa oleh pengguna atau operasi bisnis. Smoke test yang kecil namun tegas jauh lebih bernilai daripada suite besar yang lambat, rapuh, dan akhirnya diabaikan.