Bagikan melalui


Menggeser pengujian ke kiri dengan pengujian unit

Pengujian membantu memastikan bahwa kode berfungsi seperti yang diharapkan, tetapi waktu dan upaya untuk membangun pengujian membutuhkan waktu jauh dari tugas lain seperti pengembangan fitur. Dengan biaya ini, penting untuk mengekstrak nilai maksimum dari pengujian. Artikel ini membahas prinsip pengujian DevOps, berfokus pada nilai pengujian unit dan strategi pengujian shift-left.

Penguji khusus digunakan untuk menulis sebagian besar pengujian, dan banyak pengembang produk tidak belajar menulis pengujian unit. Menulis tes bisa tampak terlalu sulit atau seperti terlalu banyak pekerjaan. Mungkin ada skeptisme tentang apakah strategi pengujian unit berfungsi, pengalaman buruk dengan tes unit yang ditulis dengan buruk, atau takut bahwa pengujian unit akan menggantikan tes fungsi.

Grafik yang menjelaskan argumen tentang mengadopsi pengujian unit.

Untuk menerapkan strategi pengujian DevOps, bersikaplah pragmatis dan fokus pada membangun momentum. Meskipun Anda dapat bersikeras pada pengujian unit untuk kode baru atau kode yang ada yang dapat direfaktor dengan bersih, mungkin masuk akal bagi basis kode lama untuk menerima beberapa ketergantungan. Jika bagian signifikan dari kode produk menggunakan SQL, memungkinkan pengujian unit untuk mengambil dependensi pada penyedia sumber daya SQL alih-alih meniru lapisan tersebut bisa menjadi pendekatan jangka pendek untuk maju.

Ketika organisasi DevOps matang, menjadi lebih mudah bagi kepemimpinan untuk meningkatkan proses. Meskipun mungkin ada beberapa ketahanan terhadap perubahan, organisasi Agile menghargai perubahan yang dengan jelas membayar dividen. Seharusnya mudah untuk menjual visi eksekusi pengujian yang lebih cepat dengan lebih sedikit kegagalan, karena itu berarti lebih banyak waktu untuk berinvestasi dalam menghasilkan nilai baru melalui pengembangan fitur.

Taksonomi pengujian DevOps

Menentukan taksonomi pengujian adalah aspek penting dari proses pengujian DevOps. Taksonomi pengujian DevOps mengklasifikasikan pengujian individual berdasarkan dependensi mereka dan waktu yang mereka ambil untuk dijalankan. Pengembang harus memahami jenis pengujian yang tepat untuk digunakan dalam skenario yang berbeda, dan mengetahui pengujian mana yang diperlukan untuk berbagai bagian dari proses. Sebagian besar organisasi mengategorikan pengujian di empat tingkat:

  • Pengujian L0 dan L1 adalah pengujian unit, atau pengujian yang bergantung pada kode dalam rakitan yang sedang diuji dan tidak ada yang lain. L0 adalah kelas yang luas dari pengujian unit dalam memori yang cepat.
  • L2 adalah pengujian fungsi yang mungkin memerlukan perakitan ditambah dependensi lain, seperti SQL atau sistem file.
  • Pengujian fungsional L3 dilakukan pada penyebaran layanan yang dapat diuji. Kategori pengujian ini memerlukan penyebaran layanan, tetapi mungkin menggunakan stub untuk dependensi layanan utama.
  • Pengujian L4 adalah kelas pengujian integrasi terbatas yang berjalan di lingkungan produksi. Pengujian L4 memerlukan implementasi produk secara menyeluruh.

Meskipun ideal bagi semua tes untuk dijalankan setiap waktu, hal itu tidak memungkinkan. Teams dapat memilih di mana dalam proses DevOps untuk menjalankan setiap pengujian, dan menggunakan strategi shift-left atau shift-right untuk memindahkan berbagai jenis pengujian sebelumnya atau yang lebih baru dalam proses.

Misalnya, harapannya mungkin pengembang selalu menjalankan pengujian L2 sebelum melakukan commit, permintaan penarikan secara otomatis gagal jika eksekusi pengujian L3 gagal, dan penyebaran akan diblokir jika pengujian L4 gagal. Aturan khusus dapat bervariasi dari organisasi ke organisasi, tetapi menegakkan harapan untuk semua tim dalam organisasi memindahkan semua orang ke tujuan visi kualitas yang sama.

Panduan pengujian unit

Tetapkan panduan ketat untuk pengujian unit L0 dan L1. Tes ini harus sangat cepat dan dapat diandalkan. Misalnya, waktu eksekusi rata-rata per pengujian L0 dalam rakitan harus kurang dari 60 milidetik. Waktu eksekusi rata-rata per pengujian L1 dalam rakitan harus kurang dari 400 milidetik. Tidak ada pengujian pada tingkat ini yang melebihi 2 detik.

Satu tim Microsoft menjalankan lebih dari 60.000 pengujian unit secara paralel dalam waktu kurang dari enam menit. Tujuan mereka adalah mengurangi waktu ini menjadi kurang dari satu menit. Tim melacak waktu eksekusi pengujian unit dengan menggunakan alat seperti grafik berikut, dan mengajukan laporan kerusakan terhadap pengujian yang melebihi waktu yang diizinkan.

Bagan yang memperlihatkan fokus berkelanjutan pada waktu eksekusi pengujian.

Pedoman pengujian fungsi

Tes fungsi harus independen. Konsep utama untuk pengujian L2 adalah isolasi. Pengujian yang terisolasi dengan benar dapat berjalan dengan andal dalam urutan apa pun, karena mereka memiliki kontrol penuh atas lingkungan tempat mereka berjalan. Status harus diketahui di awal pengujian. Jika satu pengujian membuat data dan meninggalkannya dalam database, pengujian tersebut dapat merusak eksekusi pengujian lain yang bergantung pada status database yang berbeda.

Pengujian warisan yang memerlukan identitas pengguna mungkin telah memanggil penyedia autentikasi eksternal untuk mendapatkan identitas. Praktik ini memperkenalkan beberapa tantangan. Dependensi eksternal mungkin tidak dapat diandalkan atau tidak tersedia sementara waktu, mengganggu pengujian. Praktik ini juga melanggar prinsip isolasi pengujian, karena pengujian dapat mengubah status identitas, seperti izin, yang mengakibatkan status default yang tidak terduga untuk pengujian lain. Pertimbangkan untuk mencegah masalah ini dengan berinvestasi dalam dukungan identitas dalam kerangka kerja pengujian.

Prinsip pengujian DevOps

Untuk membantu transisi portofolio pengujian ke proses DevOps modern, artikulasi visi berkualitas. Tim harus mematuhi prinsip pengujian berikut saat menentukan dan menerapkan strategi pengujian DevOps.

Diagram yang menunjukkan contoh visi kualitas dan mencantumkan prinsip pengujian.

Pindahkan pengujian ke tahap lebih awal

Pengujian dapat memakan waktu lama untuk dijalankan. Saat skala proyek, angka dan jenis pengujian tumbuh secara substansial. Ketika suite pengujian tumbuh hingga memakan waktu berjam-jam atau berhari-hari untuk diselesaikan, mereka dapat mendorong lebih jauh sampai dijalankan pada saat terakhir. Manfaat kualitas kode pengujian tidak direalisasikan sampai lama setelah kode diterapkan.

Pengujian jangka panjang mungkin juga menghasilkan kegagalan yang memakan waktu untuk diselidiki. Teams dapat membangun toleransi untuk kegagalan, terutama di awal sprint. Toleransi ini merusak nilai pengujian sebagai wawasan tentang kualitas basis kode. Tes yang berjalan lama dan di menit-menit terakhir juga menambah ketidakpastian pada harapan pada akhir sprint, karena jumlah utang teknis yang tidak diketahui harus dibayar untuk membuat kode siap kirim.

Tujuan untuk menggeser pengujian ke kiri adalah untuk memindahkan kualitas upstream dengan melakukan tugas pengujian sebelumnya di alur. Melalui kombinasi peningkatan pengujian dan proses, pergeseran ke kiri mengurangi waktu yang diperlukan agar pengujian berjalan, dan dampak kegagalan nantinya dalam siklus. Menggeser ke kiri memastikan bahwa sebagian besar pengujian selesai sebelum perubahan bergabung ke cabang utama.

Diagram yang memperlihatkan pemindahan ke pengujian shift-left.

Selain menggeser tanggung jawab pengujian tertentu yang tersisa untuk meningkatkan kualitas kode, tim dapat menggeser aspek pengujian lainnya ke kanan, atau nanti dalam siklus DevOps, untuk meningkatkan produk akhir. Untuk informasi selengkapnya, lihat Pergeseran ke kanan untuk pengujian di produksi.

Menulis tes pada tingkat seendah mungkin

Tulislah lebih banyak tes unit. Mendukung pengujian dengan dependensi eksternal terkecil, dan fokus pada menjalankan sebagian besar pengujian sebagai bagian dari build. Pertimbangkan sistem build paralel yang dapat menjalankan pengujian unit untuk rakitan segera setelah perakitan dan pengujian terkait hilang. Tidak layak untuk menguji setiap aspek layanan pada tingkat ini, tetapi prinsipnya adalah menggunakan pengujian unit yang lebih ringan jika mereka dapat menghasilkan hasil yang sama dengan tes fungsi yang lebih berat.

Bertujuan untuk keandalan pengujian

Mempertahankan tes yang tidak dapat diandalkan itu mahal secara organisasi. Pengujian semacam itu bekerja langsung terhadap tujuan efisiensi rekayasa dengan membuatnya sulit untuk membuat perubahan dengan percaya diri. Pengembang harus dapat membuat perubahan di mana saja dan dengan cepat mendapatkan keyakinan bahwa tidak ada yang rusak. Pertahankan standar tinggi untuk keandalan. Mencegah penggunaan pengujian UI, karena cenderung tidak dapat diandalkan.

Menulis pengujian fungsional yang dapat berjalan di mana saja

Pengujian mungkin menggunakan titik integrasi khusus yang dirancang khusus untuk mengaktifkan pengujian. Salah satu alasan untuk praktik ini adalah kurangnya testabilitas dalam produk itu sendiri. Sayangnya, pengujian seperti ini sering bergantung pada pengetahuan internal dan menggunakan detail implementasi yang tidak masalah dari perspektif pengujian fungsional. Pengujian ini terbatas pada lingkungan yang memiliki rahasia dan konfigurasi yang diperlukan untuk menjalankan pengujian, yang umumnya mengecualikan penyebaran produksi. Pengujian fungsi hanya boleh menggunakan API publik produk.

Mendesain produk untuk uji coba

Organisasi dalam proses DevOps yang matang mengambil pandangan lengkap tentang apa artinya memberikan produk berkualitas pada ritme cloud. Menggeser keseimbangan secara signifikan ke dalam mendukung pengujian unit daripada pengujian fungsional mengharuskan tim untuk membuat pilihan desain dan implementasi yang mendukung kesesuaian pengujian. Ada ide yang berbeda tentang apa yang merupakan kode yang dirancang dengan baik dan diimplementasikan dengan baik untuk kemampuan pengujian, sama seperti ada gaya pengodean yang berbeda. Prinsipnya adalah bahwa merancang untuk uji coba harus menjadi bagian utama dari diskusi tentang desain dan kualitas kode.

Perlakukan kode pengujian sebagai kode produk

Secara eksplisit menyatakan bahwa kode pengujian adalah kode produk memperjelas bahwa kualitas kode pengujian sama pentingnya dengan pengiriman kode produk. Teams harus memperlakukan kode pengujian dengan cara yang sama seperti mereka memperlakukan kode produk, dan menerapkan tingkat perawatan yang sama pada desain dan implementasi pengujian dan kerangka kerja pengujian. Upaya ini mirip dengan mengelola konfigurasi dan infrastruktur sebagai kode. Untuk menjadi lengkap, tinjauan kode harus mempertimbangkan kode pengujian dan menilai dengan standar kualitas yang sama dengan kode produk.

Menggunakan infrastruktur pengujian bersama

Turunkan standar penggunaan infrastruktur pengujian untuk menghasilkan indikator kualitas yang dapat dipercaya. Lihat pengujian sebagai layanan bersama untuk seluruh tim. Simpan kode pengujian unit bersama kode produk dan buat dengan produk. Pengujian yang berjalan sebagai bagian dari proses build juga harus berjalan di bawah alat pengembangan seperti Azure DevOps. Jika pengujian dapat berjalan di setiap lingkungan dari pengembangan lokal melalui produksi, pengujian tersebut memiliki keandalan yang sama dengan kode produk.

Membuat pemilik kode bertanggung jawab untuk pengujian

Kode pengujian harus berada di samping kode produk dalam repositori. Agar kode diuji di batas komponen, dorong akuntabilitas dalam pengujian kepada orang yang menulis kode komponen. Jangan mengandalkan orang lain untuk menguji komponen.

Studi kasus: Geser ke kiri dengan pengujian unit

Tim Microsoft memutuskan untuk mengganti rangkaian pengujian lama mereka dengan pengujian unit DevOps modern serta pendekatan shift-left. Tim melacak kemajuan di seluruh sprint tiga kali seminggu, seperti yang ditunjukkan pada grafik berikut. Grafik mencakup sprint 78-120, yang mewakili 42 sprint selama 126 minggu, atau sekitar dua setengah tahun upaya.

Tim memulai dengan 27K pengujian warisan di sprint 78, dan mencapai nol pengujian warisan pada S120. Satu set pengujian unit L0 dan L1 menggantikan sebagian besar pengujian fungsi lama. Pengujian L2 baru menggantikan beberapa pengujian, dan banyak tes lama dihapus.

Diagram yang menunjukkan contoh keseimbangan portofolio pengujian dari waktu ke waktu.

Dalam perjalanan perangkat lunak yang membutuhkan waktu lebih dari dua tahun untuk diselesaikan, ada banyak hal yang dapat dipelajari dari proses itu sendiri. Secara keseluruhan, upaya untuk sepenuhnya mengulangi sistem pengujian selama dua tahun adalah investasi besar-besaran. Tidak setiap tim fitur melakukan pekerjaan pada saat yang sama. Banyak tim di seluruh organisasi menginvestasikan waktu di setiap sprint, dan dalam beberapa sprint, itu sebagian besar dari apa yang dilakukan tim. Meskipun sulit untuk mengukur biaya pergeseran, itu adalah persyaratan yang tidak dapat dinegosiasikan untuk kualitas tim dan tujuan performa.

Memulai Langkah Pertama

Pada awalnya, tim meninggalkan tes fungsi lama, yang disebut tes TRA, sendirian. Tim berusaha meyakinkan para pengembang untuk menerima ide menulis pengujian unit, terutama untuk fitur baru. Fokusnya adalah membuatnya semudah mungkin untuk menulis tes L0 dan L1. Tim perlu mengembangkan kemampuan tersebut terlebih dahulu, dan membangun momentum.

Grafik di atas menunjukkan jumlah pengujian unit yang mulai meningkat lebih awal, karena tim melihat manfaat dari penulisan pengujian unit. Pengujian unit lebih mudah dipertahankan, lebih cepat dijalankan, dan memiliki lebih sedikit kegagalan. Sangat mudah untuk mendapatkan dukungan untuk menjalankan semua pengujian unit dalam alur permintaan pull.

Tim tidak fokus menulis tes L2 baru hingga sprint 101. Sementara itu, jumlah pengujian TRA turun dari 27.000 menjadi 14.000 dari Sprint 78 ke Sprint 101. Pengujian unit baru menggantikan beberapa tes TRA, tetapi banyak yang hanya dihapus, berdasarkan analisis tim tentang kegunaannya.

Tes TRA melompat dari 2100 menjadi 3800 di sprint 110 karena lebih banyak pengujian ditemukan di pohon sumber dan ditambahkan ke grafik. Ternyata tes selalu berjalan, tetapi tidak dilacak dengan benar. Ini bukan krisis, tetapi penting untuk jujur dan menilai kembali sesuai kebutuhan.

Menjadi lebih cepat

Setelah tim memiliki sinyal integrasi berkelanjutan (CI) yang sangat cepat dan andal, itu menjadi indikator tepercaya untuk kualitas produk. Cuplikan layar berikut menunjukkan permintaan tarik dan alur CI (pipeline) yang sedang berjalan, serta waktu yang diperlukan untuk melalui berbagai fase.

Diagram yang memperlihatkan pull request dan pipeline CI bergulir dalam tindakan.

Dibutuhkan sekitar 30 menit dari permintaan penarikan hingga penyatuan, yang mencakup menjalankan 60.000 pengujian unit. Dari penggabungan kode ke build CI adalah sekitar 22 menit. Sinyal kualitas pertama dari CI, SelfTest, datang setelah sekitar satu jam. Kemudian, sebagian besar produk diuji dengan perubahan yang diusulkan. Dalam dua jam dari Merge ke SelfHost, seluruh produk diuji dan perubahan siap diproduksi.

Menggunakan metrik

Tim melacak kartu skor seperti contoh berikut. Pada tingkat tinggi, kartu skor melacak dua jenis metrik: Kesehatan atau utang, dan kecepatan.

Diagram yang memperlihatkan kartu skor metrik untuk melacak performa pengujian.

Untuk metrik kesehatan situs aktif, tim melacak waktu deteksi, waktu mitigasi, dan berapa banyak item perbaikan yang dibawa tim. Item perbaikan adalah pekerjaan yang diidentifikasi tim dalam retrospektif situs langsung untuk mencegah insiden serupa berulang. Kartu skor juga melacak apakah tim menutup item perbaikan dalam jangka waktu yang wajar.

Untuk metrik kesehatan rekayasa, tim melacak bug aktif per pengembang. Jika tim memiliki lebih dari lima bug per pengembang, tim harus memprioritaskan perbaikan bug tersebut sebelum pengembangan fitur baru. Tim juga melacak bug yang sudah lama dalam kategori khusus seperti keamanan.

Metrik kecepatan rekayasa mengukur kecepatan di berbagai bagian alur integrasi berkelanjutan dan pengiriman berkelanjutan (CI/CD). Tujuan keseluruhan adalah untuk meningkatkan kecepatan alur DevOps: Mulai dari ide, memasukkan kode ke dalam produksi, dan menerima data kembali dari pelanggan.

Langkah selanjutnya