Definisi
Test-Driven Development (TDD) adalah metodologi pengembangan perangkat lunak yang dimulai dengan pengujian atau testing terlebih dahulu sebelum mengimplementasikan kode program.
Dalam menerapkan metode TDD pada pengembangan perangkat lunak, terdapat tahapan-tahapan yang harus dilalui, yaitu sebagai berikut :
Write Test First
Anda harus menulis test untuk fungsionalitas yang akan diimplementasikan. Test ini harus jelas menentukan apa yang diharapkan dan menjadi requirements dari fitur yang akan ditulis nantinya. Pada tahap ini, perlu diperhatikan bahwa test seharusnya gagal karena belum ada implementasi kode yang memenuhi kriteria test tersebut. Dengan membuat test yang seharusnya gagal, kita dapat memastikan bahwa kode memang terjamin gagal karena tidak memenuhi requirements yang sebelumnya dibuat. Kegagalan test merupakan bagian krusial dari proses pengembangan yang memastikan bahwa test memenuhi persyaratan yang telah ditetapkan sebelumnya. Tahap ini juga dikenal dengan istilah ‘Red’ dalam siklus Red, Green, Refactor. Pesan commit untuk tahap ini diawali dengan label [Red]. Selain itu, pastikan bahwa semua test yang Anda buat mengacu pada acceptance criteria yang telah ditetapkan secara rinci dalam user story atau persyaratan proyek.
Then, Write the Code (Implementation)
Langkah selanjutnya adalah menulis kode implementasi yang diperlukan untuk membuat test tersebut berhasil. Pada tahap ini, Anda hanya cukup untuk memenuhi kebutuhan yang ditetapkan oleh test yang telah ditulis pada tahap pertama. Prinsip utama di sini adalah menulis kode yang cukup untuk memenuhi persyaratan test, tanpa memperhatikan aspek lain dari kode atau fungsionalitas yang tidak relevan pada tahap ini. Jangan tergoda untuk menulis kode yang lebih kompleks dari yang diperlukan hanya untuk membuat test tersebut berhasil. Setelah menulis kode implementasi, pastikan untuk menjalankan semua test yang ada dan memastikan bahwa semuanya berhasil dan berjalan sesuai dengan spesifikasi yang telah ditetapkan. Tahap ini adalah ‘Green’ dalam siklus Red, Green, Refactor. Hasil perubahan dapat di-commit dengan memberikan label [Green]. Hal ini menandakan bahwa semua testing codes telah berhasil dan kode dapat dipublikasi.
Finally, Refactor the Code
Setelah berhasil menguji kode dan memastikan bahwa semua test telah lulus, langkah berikutnya adalah melakukan refactoring. Refactoring adalah proses memperbaiki struktur kode yang sudah ada agar lebih efisien, mudah dibaca, dan mudah dipelihara, tanpa mengubah requirements dari kode tersebut. Refactoring dapat melibatkan proses seperti menyederhanakan algoritma yang kompleks ataupun mengekstraksi kode yang sering muncul menjadi fungsi yang dapat digunakan kembali. Setelah selesai melakukan refactoring, pastikan untuk menjalankan semua test lagi untuk memastikan bahwa perubahan yang Anda buat tidak memengaruhi fungsionalitas dari kode. Tahap ini adalah ‘Refactor’ dalam siklus Red, Green, Refactor dan di-commit dengan memberikan label [Refactor].
Kelebihan & Kekurangan
Seperti halnya dengan setiap metodologi, Test-Driven Development datang dengan serangkaian kelebihan dan kekurangan yang dapat mempengaruhi keputusan tim pengembang dalam mengadopsinya, sebagai berikut :
Kelebihan
- Dokumentasi terintegrasi langsung dengan kode, mempermudah akses dan pemahaman terhadap dokumentasi [1].
- Memberikan definisi kualitas fungsional yang tidak ambigu; jika test berhasil, kode dianggap berkualitas [1].
- Meningkatkan kualitas kode melalui praktik dan siklus struktur dan desain yang digunakan dalam pengembangan [1, 2, 3].
- Mendorong pemahaman struktur dan desain sebelum pengkodean, yang juga dapat berfungsi sebagai manajemen kebutuhan dan desain [3].
Kekurangan
- Adopsi TDD memerlukan waktu tambahan untuk perencanaan dan penulisan test sebelum pengembangan sehingga berpotensial memperlambat pengiriman fitur. [4]
- TDD tidak menjamin identifikasi semua bug, terutama jika ada kesalahpahaman dalam implementasi dan tujuan test. [2, 4]
- Pemeliharaan dan pembaruan test menjadi lebih menuntut setiap kali kebutuhan berubah, memperberat proses pengembangan. [3, 4]
Update : Membuat Test dengan Lengkap dan Bersih
Setelah kita memahami apa itu TDD, selanjutnya, kita harus mengetahui bagaimana cara membuat test yang lengkap, di mana test harus mencakup success, failed, dan corner case. Apa ketiganya itu?
Success Case
Seperti namanya, test ini merujuk kepada output dengan hasil yang diharapkan atau requirements yang telah ditetapkan. Contoh implementasinya adalah pada fungsi menghapus objek yaitu jadwal dengan fungsi sebagai berikut :
Di sini, kita perlu menguji apakah fungsi delete tersebut berhasil sesuai dengan ekspektasi yaitu menghapus objek yang diberikan sesuai dengan id dan mengirimkan respons sukses. Berikut test untuk success case tersebut :
Failed Case
Case ini mengacu pada test dengan situasi di mana sistem tidak berjalan sesuai dengan requirements. Dengan fungsi yang masih sama dengan success case, kita perlu membuat test untuk failed case di mana id yang diberikan tidak terdaftar pada jadwal. Berikut implementasinya :
Corner Case
Corner case atau biasa disebut edge case mengacu pada test dengan situasi yang tidak biasa / ekstrem/ atau paling ujung (di titik maksimum atau minimum). Corner case penting untuk diperhatikan karena sistem yang baik harus robust dan dapat diandalkan dalam berbagai kondisi. Contohnya adalah fungsi untuk menghitung akar kuadrat dari sebuah angka. Corner case di sini adalah user bisa jadi mengirimkan nilai negatif yang di mana secara matematis, nilai negatif tidak bisa memiliki akar kuadrat dalam bilangan real.
Selanjutkan, bagaimana cara membuat kode test yang bersih?. Bersih atau Clean Test mengacu kepada prinsip F.I.R.S.T. atau singkatan dari Fast, Independent, Repeatable, Self-Validating, dan Timely.
1. Fast : Test harus cepat berjalan untuk mempercepat siklus pengembangan dan meningkatkan produktifitas developer.
2. Independent : Setiap test harus independen dari test lainnya di mana eksekusi satu test tidak bergantung dengan kondisi dari test lain. Dengan begitu, test dapat lebih mudah dipahami oleh developer dan lebih mudah dijaga karena jika test gagal, kita dapat tahu di mana sumber masalahnya.
3. Repeatable : Test dapat diulang sehingga, kapanpun dan dimanapun, perilaku dari test tersebut dapat berjalan dengan hasil yang sama sehingga test konsisten dan dapat diandalkan.
4. Self-Validating : Test harus menjalankan operasi dan dapat mengecek hasilnya pada programnya sendiri, sehingga kita tidak perlu melakukan operasi atau pengecekan secara manual. Hasil dari test juga jelas yaitu “success” atau “failed”.
5. Timely : Test harus ditulis pada waktu yang tepat yaitu saat kode produksi sedang diuji.
Implementasi TDD dalam Flutter
Pada proyek ini, kita akan membuat dialog modal “Game Over” dengan requirements yaitu modal dapat memberikan pemain feedback langsung tentang performa mereka di akhir sesi permainan. Modal ini akan menampilkan skor permainan saat ini, skor tertinggi yang telah dicapai, dan menawarkan opsi untuk bermain lagi atau kembali ke menu utama.
Step 1 – Mempersiapkan Lingkungan Flutter dan Struktur File
Pastikan Anda telah menginstal Flutter di komputer Anda. Anda bisa mengikuti panduan instalasi resmi di situs Flutter.
Step 2 – Menulis kode testing
Sebelum menulis kode implementasi, tulis test yang menggambarkan requirements yang diharapkan dari fitur yang ingin dibuat. Dalam Flutter, terdapat tiga macam teting yaitu bisa berupa unit test — untuk satu logika bisnis atau fungsi , widget test — untuk antarmuka pengguna dan interaksi widget, atau integration test — untuk alur kerja aplikasi secara keseluruhan, tergantung pada aspek aplikasi yang Anda kerjakan.
Step 3 – Implementasi kode
Setelah merancang kode testing, lanjutkan dengan mengembangkan implementasi kode yang diperlukan untuk memenuhi kriteria requirements test tersebut.
Step 4 – Refactoring
Kemudian, saya melakukan refactoring kode untuk meningkatkan kualitas dan kemudahan readability. Pada kasus ini, saya mengambil kode yang sering muncul dan mengekstraknya menjadi fungsi yang dapat digunakan kembali. Setelah itu, ulangi test untuk memastikan bahwa hasil kode dari refactoring berjalan dengan baik.
Step 5 – Melihat Laporan Code Coverage
Jika Anda ingin melihat laporan code coverage bersamaan dengan menjalankan test, gunakan perintah:
Step 6 (Lebih Advanced) — Static Code Analysis dengan SonarQube
Setelah melakukan commit terakhir, kita dapat melihat hasil dari SonarQube. Hal ini penting untuk mengecek apakah kode kita terbebas dari issues seperti bugs, vulnerabilites, ataupun code smells. Dapat dilihat pada SonarQube, code coverage dari file game_over_modal.dart sudah 100% dan tanpa ada bugs, vulnerability, code smells, maupun security hotspots, sehingga merupakan indikasi bahwa code kita memiliki kualitas yang baik.