Strategi test workflow aplikasi fellowship agar lolos regression perlu dirancang dari awal, bukan ditambal setelah bug muncul di produksi. Untuk produk seperti aplikasi fellowship, grant, atau opportunity developer, masalah umumnya bukan hanya validasi field, tetapi interaksi antar-langkah: form panjang, upload berkas, deadline, email async, dan perubahan status review yang harus konsisten.

Artikel ini membahas pendekatan yang praktis untuk menguji workflow tersebut dengan test pyramid, pembagian unit/integration/E2E, contract test API, data uji yang representatif, pencegahan flaky test, checklist regression sebelum rilis, dan contoh workflow CI yang stabil. Fokusnya adalah bagaimana menangkap bug yang benar-benar sering lolos pada sistem aplikasi peluang developer.

Mengapa workflow aplikasi fellowship sering gagal saat regression

Aplikasi fellowship atau grant cenderung memiliki alur yang terlihat sederhana dari UI, tetapi kompleks di belakang layar. Satu submit final bisa melibatkan banyak komponen:

  • Validasi field wajib dan kondisional.
  • Upload CV, proposal, atau portofolio.
  • Penyimpanan draft sebelum submit final.
  • Validasi deadline berdasarkan zona waktu.
  • Pengiriman email konfirmasi atau notifikasi reviewer.
  • Perubahan status review: draft, submitted, under_review, accepted, rejected.
  • Integrasi dengan object storage, queue, atau service email.

Bug regression biasanya muncul saat satu perubahan kecil memengaruhi kontrak alur yang lain. Contoh nyata:

  • Refactor validasi frontend membuat field opsional terkirim sebagai string kosong, lalu backend menolaknya.
  • Perubahan aturan deadline membuat aplikasi masih bisa disubmit setelah batas waktu di zona waktu tertentu.
  • Upload sukses di lokal tetapi gagal di CI karena test bergantung pada file system sementara.
  • Email konfirmasi kadang tidak terkirim saat queue lambat, lalu test E2E menjadi flaky.
  • Status review berubah tanpa audit atau tanpa memicu notifikasi yang diharapkan.

Karena itu, strategi testing harus memetakan risiko bisnis ke jenis test yang tepat, bukan sekadar mengejar coverage angka tinggi.

Menyusun test pyramid untuk workflow aplikasi fellowship

Test pyramid membantu menyeimbangkan kecepatan, stabilitas, dan cakupan. Untuk workflow aplikasi fellowship, pendekatan yang sehat biasanya:

  • Unit test paling banyak: menguji aturan bisnis dan fungsi murni.
  • Integration test secukupnya: menguji API, database, queue boundary, object storage adapter, dan event.
  • E2E test sedikit tetapi kritis: menguji alur utama yang benar-benar penting bagi pengguna.

Apa yang masuk ke unit test

Unit test cocok untuk logika yang deterministik dan tidak perlu browser, network, atau storage sungguhan. Fokus utamanya adalah aturan bisnis yang jika salah akan merusak banyak alur.

Contoh target unit test:

  • Validasi kapan aplikasi boleh disubmit.
  • Aturan field kondisional, misalnya URL GitHub wajib jika memilih track engineering.
  • Perhitungan status berdasarkan event tertentu.
  • Pemeriksaan file type dan ukuran secara logis sebelum diteruskan ke layer penyimpanan.
  • Deadline check berbasis waktu dan zona waktu.
function canSubmit(application, now, deadline) {
  if (application.status !== 'draft') return false;
  if (now > deadline) return false;
  if (!application.profileCompleted) return false;
  if (!application.documents.cvUploaded) return false;
  return true;
}

// Contoh test case
assert(canSubmit(draftCompleteApp, beforeDeadline, deadline) === true)
assert(canSubmit(draftCompleteApp, afterDeadline, deadline) === false)
assert(canSubmit(submittedApp, beforeDeadline, deadline) === false)

Nilai unit test ada pada kecepatan dan presisi. Ketika aturan submit berubah, Anda bisa tahu bagian mana yang pecah tanpa harus menunggu browser test selesai.

Apa yang masuk ke integration test

Integration test penting untuk memastikan komponen yang berbeda benar-benar bekerja bersama. Pada sistem fellowship, lapisan ini biasanya memberi ROI tertinggi karena banyak bug muncul di perbatasan antar-sistem.

Contoh integration test yang relevan:

  • API POST /applications menyimpan draft ke database dengan skema yang benar.
  • API submit final memvalidasi deadline dan mengubah status ke submitted.
  • Upload file memanggil storage adapter dan menyimpan metadata dokumen.
  • Submit final memicu event atau job pengiriman email konfirmasi.
  • Perubahan status review membuat audit log tercatat.

Jika memungkinkan, gunakan dependency nyata untuk database test, tetapi fake atau stub untuk layanan eksternal yang tidak perlu dibawa ke setiap test, seperti provider email publik. Prinsipnya: uji integrasi internal secara nyata, dan eksternal secara terkendali.

Apa yang masuk ke E2E test

E2E test tidak perlu banyak, tetapi harus melindungi alur yang paling kritis. Untuk aplikasi fellowship, umumnya cukup 5-10 skenario inti yang stabil.

Contoh E2E prioritas tinggi:

  1. Pengguna membuat draft, mengisi form bertahap, upload CV, lalu submit sebelum deadline.
  2. Pengguna gagal submit karena field wajib belum lengkap.
  3. Pengguna gagal submit setelah deadline.
  4. Reviewer mengubah status aplikasi menjadi under_review lalu accepted.
  5. Email konfirmasi muncul sebagai efek submit yang berhasil, diverifikasi melalui inbox test atau event sink.

Kesalahan umum adalah memindahkan terlalu banyak logika verifikasi ke E2E. Akibatnya suite lambat, rapuh, dan sulit di-debug. Simpan E2E untuk membuktikan bahwa alur utama benar-benar hidup dari ujung ke ujung.

Pembagian skenario test berdasarkan risiko workflow

Supaya regression test tidak melebar tanpa arah, kelompokkan skenario berdasarkan risiko produk.

1. Form panjang dan draft multi-langkah

Masalah yang sering terjadi:

  • Data hilang saat pindah langkah.
  • Autosave menimpa jawaban lama dengan nilai kosong.
  • Validasi berbeda antara frontend dan backend.

Yang perlu diuji:

  • Unit test untuk aturan validasi dan normalisasi input.
  • Integration test untuk penyimpanan draft parsial.
  • E2E untuk melanjutkan draft yang sudah tersimpan.

2. Upload berkas

Masalah yang sering terjadi:

  • Ukuran file melebihi batas tetapi lolos di frontend.
  • MIME type terdeteksi berbeda antara lokal dan CI.
  • Metadata file tidak sinkron dengan object storage.

Yang perlu diuji:

  • Unit test untuk aturan file yang diterima.
  • Integration test untuk penyimpanan metadata dan pemanggilan adapter storage.
  • E2E hanya untuk satu alur upload sukses dan satu alur gagal yang paling kritis.

3. Validasi deadline

Ini area yang sering memicu bug produksi karena bergantung pada waktu. Penyebab umumnya adalah perbedaan zona waktu server, klien, dan aturan program.

Yang perlu diuji:

  • Unit test dengan waktu yang dibekukan (frozen time).
  • Integration test API submit saat tepat sebelum dan sesudah deadline.
  • Kasus transisi tanggal dan jam, terutama bila deadline didefinisikan dalam zona waktu tertentu.

Jangan biarkan test memakai waktu sistem aktual tanpa kontrol. Gunakan abstraksi clock atau mekanisme freeze time agar hasil test deterministik.

4. Email konfirmasi dan notifikasi reviewer

Masalah utamanya bukan hanya isi email, tetapi kapan dan bagaimana email dijadwalkan.

Yang perlu diuji:

  • Integration test bahwa submit final mem-publish event atau enqueue job.
  • Test template email terpisah bila sistem Anda merender konten dinamis.
  • E2E tidak harus mengirim email nyata; cukup verifikasi email masuk ke mailbox test atau sink lokal.

5. Status review

Status sering jadi sumber inkonsistensi bila transisinya tidak dibatasi. Misalnya, aplikasi yang sudah rejected tiba-tiba kembali ke submitted tanpa audit.

Yang perlu diuji:

  • Unit test untuk state transition yang valid dan invalid.
  • Integration test bahwa perubahan status memperbarui audit log dan notifikasi yang tepat.
  • E2E reviewer flow secukupnya untuk jalur utama.
const allowedTransitions = {
  draft: ['submitted'],
  submitted: ['under_review', 'withdrawn'],
  under_review: ['accepted', 'rejected'],
  accepted: [],
  rejected: []
}

function canTransition(from, to) {
  return allowedTransitions[from]?.includes(to) ?? false
}

Contract test API untuk mencegah mismatch frontend-backend

Pada workflow aplikasi fellowship, frontend dan backend sering berkembang paralel. Bug umum terjadi saat salah satu pihak mengubah struktur request atau response tanpa terdeteksi.

Contract test API membantu memastikan keduanya tetap sepakat tentang:

  • Nama field dan tipe data.
  • Field wajib vs opsional.
  • Format error validasi.
  • Struktur response status aplikasi.
  • Representasi metadata file upload.

Contoh kontrak yang penting:

  • POST /applications/draft menerima payload parsial.
  • POST /applications/{id}/submit mengembalikan status final dan timestamp submit.
  • GET /applications/{id} selalu memuat shape status yang konsisten untuk frontend.

Anda tidak harus memakai tool tertentu, tetapi prinsipnya sama: kontrak ditulis eksplisit, diverifikasi otomatis, dan dijalankan di pipeline. Ini sangat membantu jika ada tim frontend, backend, dan QA yang bergerak terpisah.

{
  "id": "app_123",
  "status": "submitted",
  "submittedAt": "2026-07-03T10:00:00Z",
  "documents": {
    "cv": {
      "fileName": "cv.pdf",
      "uploaded": true
    }
  },
  "errors": []
}

Trade-off-nya, contract test menambah artefak yang perlu dirawat. Namun untuk produk dengan form kompleks dan banyak validasi, biaya perawatannya biasanya sepadan karena mencegah mismatch yang mahal di akhir sprint.

Dataset uji yang realistis, kecil, dan mudah dipahami

Salah satu penyebab test sulit dirawat adalah data uji yang terlalu besar atau terlalu acak. Untuk workflow fellowship, siapkan dataset yang merepresentasikan kondisi bisnis penting, bukan dump produksi.

Dataset minimum yang sebaiknya ada

  • Applicant draft lengkap: siap submit sebelum deadline.
  • Applicant draft tidak lengkap: ada field wajib yang kosong.
  • Applicant setelah deadline: data valid tetapi submit harus gagal.
  • Applicant dengan dokumen invalid: ukuran atau tipe file ditolak.
  • Application under review: untuk skenario reviewer.
  • Application accepted/rejected: untuk menguji state terminal.

Praktik yang disarankan:

  • Gunakan builder atau factory agar data test eksplisit dan mudah dimodifikasi.
  • Berikan nama yang menjelaskan niat bisnis, bukan nama generik seperti test1.
  • Hindari ketergantungan antartest pada data yang sama.
  • Reset database atau gunakan transaction rollback sesuai kebutuhan lingkungan test.
function makeApplication(overrides = {}) {
  return {
    status: 'draft',
    profileCompleted: true,
    documents: {
      cvUploaded: true,
      proposalUploaded: false
    },
    track: 'engineering',
    githubUrl: 'https://github.com/example',
    ...overrides
  }
}

const incompleteApplication = makeApplication({
  profileCompleted: false
})

Data seperti ini jauh lebih mudah dibaca daripada fixture besar yang isinya tidak jelas relevansinya.

Mencegah flaky test pada upload file dan email async

Flaky test adalah musuh utama regression suite. Pada workflow aplikasi fellowship, dua area paling rawan adalah upload file dan proses email async.

Flaky test pada upload file

Penyebab umum:

  • Test bergantung pada path file lokal yang tidak konsisten.
  • Pemeriksaan MIME type berbeda antar lingkungan.
  • Upload menunggu proses async yang tidak disinkronkan dengan baik.
  • Nama file acak menyebabkan assertion rapuh.

Cara menguranginya:

  • Gunakan file test kecil yang disimpan dalam direktori fixture repository.
  • Assert pada atribut yang stabil, seperti status upload dan metadata inti, bukan nama path sementara penuh.
  • Mock atau fake layer storage bila tujuan test bukan menguji provider object storage sungguhan.
  • Bila perlu menguji alur async, tunggu sinyal yang tepat, misalnya event selesai atau status database berubah, bukan sekadar sleep.

Flaky test pada email async

Penyebab umum:

  • Test mengasumsikan email terkirim sinkron padahal memakai queue.
  • Worker belum memproses job saat assertion dijalankan.
  • Mailbox test tidak dibersihkan antar test.

Cara menguranginya:

  • Pisahkan test enqueue job dari test delivery email.
  • Pada integration test, verifikasi job atau event sudah dibuat.
  • Pada E2E, gunakan mailbox sandbox, inbox test, atau email sink lokal yang bisa dipoll dengan timeout wajar.
  • Hindari assertion pada timestamp yang terlalu presisi.

Prinsip pentingnya: uji efek yang relevan pada level yang tepat. Jika yang ingin dibuktikan adalah bahwa submit memicu notifikasi, integration test cukup memverifikasi event/job. Tidak semua test harus menunggu email benar-benar terkirim ke provider eksternal.

Checklist regression sebelum rilis

Checklist regression membantu tim fokus pada alur yang benar-benar berisiko. Untuk aplikasi fellowship, berikut daftar yang layak dijadikan baseline sebelum deploy:

  1. Draft dan autosave
    • Draft baru bisa dibuat.
    • Perubahan field tersimpan dan bisa dimuat ulang.
    • Field kosong tidak menimpa data valid secara tidak sengaja.
  2. Validasi submit
    • Submit sukses sebelum deadline.
    • Submit gagal jika data belum lengkap.
    • Submit gagal setelah deadline.
    • Pesan error validasi konsisten antara API dan UI.
  3. Upload dokumen
    • File valid bisa diupload.
    • File invalid ditolak dengan error yang jelas.
    • Metadata dokumen tersimpan benar.
  4. Email dan event async
    • Submit memicu email konfirmasi.
    • Status review memicu notifikasi reviewer bila memang diharapkan.
  5. Status review
    • Transisi status valid berhasil.
    • Transisi status invalid ditolak.
    • Audit log tercatat.
  6. Keamanan dasar
    • Applicant tidak bisa mengakses aplikasi milik user lain.
    • Reviewer tidak bisa mengubah data di luar hak aksesnya.
    • Endpoint upload dan submit memerlukan otorisasi yang benar.
  7. Stabilitas API
    • Contract test lulus.
    • Shape response utama tidak berubah diam-diam.

Checklist ini bisa dipetakan ke smoke test pasca-deploy dan regression test pre-release.

Contoh workflow CI untuk verifikasi yang stabil

CI yang baik tidak harus rumit, tetapi harus memisahkan lapisan verifikasi sesuai biaya dan nilainya. Strategi yang umum efektif:

Tahap CI yang disarankan

  1. Static checks cepat: lint, format, type check bila ada.
  2. Unit test: berjalan paralel dan wajib lulus cepat.
  3. Integration test: memakai database test dan service dependency minimum.
  4. Contract test: dijalankan untuk endpoint yang menyokong frontend utama.
  5. E2E smoke: hanya skenario kritis pada setiap pull request atau merge ke branch utama.
  6. E2E regression penuh: bisa dijalankan terjadwal, sebelum rilis, atau saat perubahan menyentuh area sensitif.
name: ci

on:
  pull_request:
  push:
    branches: [main]

jobs:
  static-checks:
    steps:
      - checkout
      - install dependencies
      - run lint
      - run type-check

  unit-tests:
    steps:
      - checkout
      - install dependencies
      - run unit tests

  integration-tests:
    services:
      - database
      - redis
    steps:
      - checkout
      - install dependencies
      - run migrations
      - run integration tests

  contract-tests:
    steps:
      - checkout
      - install dependencies
      - run api contract tests

  e2e-smoke:
    needs: [unit-tests, integration-tests]
    steps:
      - checkout
      - start app
      - run e2e smoke tests

Beberapa praktik penting agar CI stabil:

  • Jangan campur seluruh E2E ke setiap commit jika durasinya membuat feedback terlalu lambat.
  • Gunakan retry dengan hati-hati. Retry boleh untuk gangguan infrastruktur sementara, tetapi jangan dijadikan penutup flaky test yang tidak diperbaiki.
  • Publikasikan artefak debug saat gagal: screenshot, video, log server, log queue, dan payload request penting.
  • Pastikan seed data CI deterministik.
  • Jalankan test dengan konfigurasi yang mendekati produksi untuk area sensitif seperti queue, storage adapter, dan timezone.

Debugging saat regression lolos dari test

Jika bug workflow tetap lolos, biasanya masalahnya bukan sekadar kurang jumlah test, tetapi salah penempatan test.

Pertanyaan diagnosis yang berguna:

  • Apakah bug terjadi di aturan bisnis murni? Jika ya, seharusnya ada unit test.
  • Apakah bug muncul saat dua komponen berinteraksi? Jika ya, tambahkan integration test di boundary tersebut.
  • Apakah bug hanya tampak dari sudut pandang pengguna akhir? Jika ya, pertimbangkan E2E atau smoke test.
  • Apakah bug berasal dari mismatch payload API? Jika ya, contract test lebih relevan daripada menambah E2E.
  • Apakah test gagal acak karena waktu, file, atau queue? Jika ya, perbaiki determinisme lingkungan test.

Jangan langsung menulis E2E baru untuk setiap bug. Tambahkan test pada lapisan terendah yang masih bisa membuktikan bug tersebut. Ini menjaga suite tetap cepat dan mudah dirawat.

Penutup

Strategi test workflow aplikasi fellowship agar lolos regression bergantung pada disiplin memilih level test yang tepat. Unit test melindungi aturan bisnis seperti deadline dan transisi status. Integration test menangkap masalah di API, database, queue, dan storage. E2E memastikan jalur utama pengguna benar-benar berfungsi. Contract test mencegah frontend dan backend saling menyimpang.

Jika Anda membangun produk untuk aplikasi fellowship, grant, atau opportunity developer, fokuslah pada area yang paling sering rusak: form panjang, upload berkas, validasi deadline, email async, dan review status. Dengan dataset uji yang realistis, pencegahan flaky test, checklist regression yang jelas, dan CI yang berlapis, peluang bug lolos ke produksi akan turun tanpa membuat pipeline menjadi lambat dan rapuh.