Pipeline CI/CD Saya Berhasil Selama 3 Bulan — Lalu Saya Membaca Log-nya

Tanda centang hijau terasa menyenangkan. Setiap pull request berhasil. Setiap deploy berjalan lancar.

Lalu seorang pengguna melaporkan fitur yang rusak. Fitur tersebut sudah rusak selama berminggu-minggu.

Saya membuka log pipeline. Hasil build kami yang berhasil ternyata membohongi kami.

Proses kami terlihat sempurna:

  • Linting
  • Unit tests
  • Integration tests
  • Build
  • Deploy

Setiap langkah memiliki tingkat keberhasilan 100% selama berbulan-bulan.

Tombol ekspor tidak melakukan apa pun saat diklik. Tidak ada kesalahan yang muncul. Saya melacaknya kembali ke sebuah perubahan dari 11 minggu yang lalu. Pipeline berhasil. Code review disetujui. Fitur tersebut sudah rusak sejak awal.

Masalahnya bukan pada kode kami. Masalahnya ada pada kode pengujian kami.

Integration tests kami menggunakan mock untuk segalanya. Kami melakukan mock pada seluruh layanan ekspor. Pengujian tersebut memeriksa mock alih-alih kode yang sebenarnya. Mock tersebut selalu mengembalikan status sukses.

Kami terjebak dalam jebakan over-mocking:

  • Unit tests: Melakukan mock pada segalanya untuk mengisolasi unit. Ini tidak apa-apa.
  • Integration tests: Melakukan mock pada segalanya demi kecepatan. Ini adalah sebuah kesalahan.
  • E2E tests: Melewatkan alur spesifik ini.

Integration tests kami hanyalah unit tests yang mahal. Mereka memverifikasi bahwa mock kami berfungsi. Mereka tidak memverifikasi bahwa kode kami berfungsi.

Saya melakukan tiga perubahan untuk memperbaikinya:

  1. Batasi mock hanya untuk unit tests. Integration tests harus mengakses database, API, dan sistem file yang sebenarnya. Jika sebuah pengujian lambat, jangan sembunyikan dengan mock. Gunakan kecepatan tersebut sebagai sinyal untuk melakukan optimasi.

  2. Tambahkan contract tests. Ini memastikan mock Anda sesuai dengan perilaku layanan yang sebenarnya. Jika sebuah mock mengembalikan data yang tidak akan diberikan oleh layanan asli, maka contract test akan gagal.

  3. Pantau coverage yang sebenarnya. Kami berhenti melihat tingkat keberhasilan (pass rate) yang sederhana. Kami melihat apa yang sebenarnya dijalankan oleh pengujian tersebut. Angka coverage kami turun dari 94% menjadi 67%. Ini adalah metrik paling jujur yang kami miliki.

Pipeline yang berwarna hijau bukan berarti kode Anda berfungsi. Itu berarti pengujian Anda berhasil. Keduanya adalah hal yang berbeda.

Bug yang paling berbahaya adalah bug yang dikatakan aman oleh pipeline Anda.

Tanyakan hal-hal ini pada diri Anda:

  • Apakah pengujian saya menangkap bug atau hanya mengonfirmasi mock?
  • Apakah integration tests saya benar-benar melakukan integrasi?
  • Jika saya menghapus semua mock, berapa banyak pengujian yang masih berhasil?
  • Apakah saya mengukur coverage atau tingkat keyakinan (confidence)?

Pipeline yang tidak pernah gagal bukanlah sesuatu yang dapat diandalkan. Itu berarti tidak teruji.

Sumber: https://dev.to/kollittle/my-cicd-pipeline-passed-for-3-months-then-i-read-the-logs-4mbj