Kenapa Checklist Tes TypeScript Penting untuk Deteksi Flaky dan Cegah Regresi

Masalah flaky test dan regresi muncul ketika rangkaian pengujian tidak konsisten atau tidak mencakup perubahan kritis. Checklist Tes TypeScript membantu tim memastikan unit, integrasi, dan end-to-end tetap terpercaya. Dalam artikel ini, kita menerapkan prinsip dari referensi dev.to "You’re a Real TypeScript Developer Only If..." untuk menyusun strategi uji yang terukur dan terintegrasi ke alur pengembangan.

Kita akan langsung melihat praktik: checklist unit hingga gate CI, cara mendeteksi serta mengatasi flaky test, lalu langkah-langkah observasi hasil tes guna menjaga stabilitas tanpa memaksa false positive.

1. Checklist Unit Test yang Konsisten dan Tidak Flaky

Unit test harus cepat dijalankan dan deterministik. Checklist dasar termasuk:

  • Pastikan semua file TypeScript dikompilasi tanpa error sebelum menjalankan jest/ vitest, agar jenis error kompilasi tidak tersamar sebagai test failure.
  • Gunakan mocking eksplisit untuk dependensi eksternal dan hindari polling waktu nyata yang menyebabkan time-based flaky.
  • Periksa coverage threshold untuk modul kritis, tetapi jangan memaksakan angka yang tidak realistis.
  • Masukkan linting tipe (tsc --noEmit) ke dalam skrip pra-test agar perubahan tipe yang tidak aman gagal lebih awal.

Contoh skrip npm:

"scripts": {
  "type-check": "tsc --noEmit",
  "test:unit": "npm run type-check && jest --runInBand"
}

Menjalankan jest dengan --runInBand menghindari race condition pada modul global. Jika tes unit tetap flaky, catat modul penyebabnya lalu pertimbangkan isolasi lebih lanjut.

2. Checklist Integrasi yang Memvalidasi Kontrak Antar Modul

Testing integrasi TypeScript bertujuan memverifikasi interaksi antar lapisan seperti service dan repository.

  • Gunakan database in-memory atau container snapshot (misal sqlite memory, PostgreSQL via Testcontainers) agar environment reset setiap tes.
  • Jaga seed data deterministik dengan fixture yang di-reset sebelum tiap suite.
  • Tambahkan assertion pada API contract (response shape, error handling) sehingga perubahan struktur terdeteksi.
  • Jalankan dalam mode serial jika state global sulit di-reset.

Berikut contoh setup Testcontainers singkat:

import { GenericContainer } from 'testcontainers';

let container;
beforeAll(async () => {
  container = await new GenericContainer('postgres:latest')
    .withEnv('POSTGRES_DB', 'test')
    .withExposedPorts(5432)
    .start();
});

afterAll(async () => {
  await container.stop();
});

Testcontainers memastikan snapshot environment bersih, memberi landasan yang konsisten untuk checklist integrasi.

3. Checklist End-to-End (E2E) dengan Observabilitas dan Antiflaky

E2E harus meniru alur pengguna. Checklist untuk mencegah flake:

  • Gunakan browser driver yang stabil seperti Playwright dengan mode headless yang sama di lokal dan CI.
  • Tambahkan assertions berbasis state yang deterministik seperti pengecekan DOM statis, bukan waktu load.
  • Implementasikan retry logic untuk network call yang tidak kritis, disertai log lengkap agar mudah di-debug.
  • Ambil screenshot dan trace saat gagal untuk observasi regresi.

Contoh konfigurasi Playwright di CI:

projects:
  - name: chromium
    use:
      headless: true
      screenshot: only-on-failure
      trace: on-first-retry

Pengaturan trace membantu mengevaluasi flaky yang muncul hanya pada percobaan kedua.

4. Checklist Pra-commit untuk Menyaring Masalah Sebelum Push

Pra-commit otomatis memastikan kualitas sebelum commit diterima.

  • Lint dan formatting: eslint --ext .ts dan prettier --check.
  • Unit test ringkas dengan tag fast atau smoke untuk memverifikasi area inti.
  • Type-check incremental hanya pada paket yang berubah menggunakan tools seperti ts-node-dev + tsconfig references.
  • Gunakan husky dan lint-staged untuk menjalankan skrip hanya pada file terubah.

Contoh konfigurasi husky:

npx husky add .husky/pre-commit "npm run lint && npm run type-check && npm run test:unit -- --runInBand"

Pra-commit menjaga agar checklist unit dijalankan sebelum kode menyebar ke remote.

5. Checklist Gate CI untuk Menjaga Repositori Tetap Stabil

Gate CI memastikan integrasi, regression, serta deteksi flaky sebelum merge.

  • CI pipeline dibagi tahap: build → unit → integrasi → e2e (khusus branch release).
  • Gunakan pipeline caching (node_modules, pnpm store) agar tes tidak timeout karena install ulang.
  • Harus memeriksa coverage delta untuk modul yang berubah, bukan keseluruhan.
  • Jalankan tes dua kali bila flake sering muncul: stage awal dengan retry terbatas di job yang sama.

Contoh snippet GitHub Actions untuk retry:

- name: Run unit tests
  run: npm run test:unit
  retry: 2

Retry terkontrol membantu mendeteksi error fluke tanpa memaksa false negative.

6. Penanganan Flaky Test dan Pencegahan Regresi

Flaky muncul karena kondisi lingkungan variabel, race, atau dependensi eksternal.

  • Log detail stack trace dan snapshot environment (container, database) saat failure.
  • Gunakan tagging pada test (misal @flaky) untuk memprioritaskan debugging.
  • Isolasi state lewat dependency injection yang mudah dimock.
  • Gunakan observability di CI: metrics failure rate, durasi tes, dan banyaknya retry.

Praktik pencegahan regresi:

  • Linting schema API dengan OpenAPI/JSON Schema di pipeline sebelum run e2e.
  • Static typing enforcement sehingga perubahan interface langsung gagal kompilasi.
  • Snapshot testing untuk UI dan API ditinjau secara berkala untuk menghindari false negative.

7. Observasi Hasil Tes dan Tindak Lanjut

Observabilitas membantu mengidentifikasi pola flaky:

  • Integrasikan hasil tes dengan dashboard SIEM atau CI artifact sehingga failure log mudah diakses.
  • Analisa flake rate per job untuk fokus perbaikan.
  • Gunakan komentar otomatis di PR dengan link rerun log agar reviewer tahu status tes terbaru.

Setiap failure harus ditindaklanjuti dengan: reproduksi lokal, menentukan apakah perlu isolation tambahan, lalu dokumentasikan di checklist regresi.

Kesimpulan

Checklist Tes TypeScript diperlukan agar regression tetap terdeteksi sedini mungkin tanpa terganggu flaky test. Gabungan unit, integrasi, e2e, pra-commit, dan gate CI dari referensi dev.to memberi pendekatan terukur: hindari noise, perkuat observabilitas, dan dokumentasikan temuan. Dengan rutinitas ini, tim bisa mempertahankan stabilitas saat skala kode meningkat.