Saya sedang mengerjakan pembanding daftar untuk membantu menyortir daftar hasil pencarian yang tidak teratur per persyaratan yang sangat spesifik dari klien kami. Persyaratan membutuhkan algoritme relevansi yang diperingkat dengan aturan berikut sesuai kepentingan:
- Pencocokan tepat pada nama
- Semua kata permintaan pencarian dalam nama atau sinonim dari hasil
- Beberapa kata permintaan pencarian dalam nama atau sinonim dari hasil (% menurun)
- Semua kata dari permintaan pencarian dalam deskripsi
- Beberapa kata dari permintaan pencarian dalam deskripsi (% menurun)
- Tanggal modifikasi terakhir turun
Pilihan desain alami untuk pembanding ini tampaknya adalah peringkat skor berdasarkan kekuatan 2. Jumlah aturan yang kurang penting tidak akan pernah lebih dari kecocokan positif pada aturan kepentingan yang lebih tinggi. Ini dicapai dengan skor berikut:
- 32
- 16
- 8 (skor tie-breaker sekunder berdasarkan% menurun)
- 4
- 2 (skor tie-breaker sekunder berdasarkan% menurun)
- 1
Dalam semangat TDD saya memutuskan untuk memulai dengan unit test saya terlebih dahulu. Untuk memiliki test case untuk setiap skenario yang unik akan ada setidaknya 63 case test unik yang tidak mempertimbangkan test case tambahan untuk logika tie breaker sekunder pada aturan 3 dan 5. Ini sepertinya sombong.
Namun, tes yang sebenarnya akan lebih sedikit. Berdasarkan aturan aktual itu sendiri, aturan tertentu memastikan bahwa aturan yang lebih rendah akan selalu benar (Misalnya. Ketika 'Semua kata Permintaan Pencarian muncul dalam deskripsi' maka aturan 'Beberapa kata Permintaan Pencarian muncul dalam deskripsi' akan selalu benar). Masih apakah tingkat upaya dalam menulis setiap kasus uji ini sepadan? Apakah ini tingkat pengujian yang biasanya diperlukan ketika berbicara tentang cakupan pengujian 100% dalam TDD? Jika tidak maka apa yang akan menjadi strategi pengujian alternatif yang dapat diterima?
sumber
Jawaban:
Pertanyaan Anda menyiratkan bahwa TDD ada hubungannya dengan "menulis semua kasus uji terlebih dahulu". IMHO itu bukan "dalam semangat TDD", sebenarnya itu menentangnya . Ingatlah bahwa TDD adalah singkatan dari "test driven development", jadi Anda hanya perlu test case yang benar-benar "mendorong" implementasi Anda, tidak lebih. Dan selama implementasi Anda tidak dirancang sedemikian rupa sehingga jumlah blok kode tumbuh secara eksponensial dengan setiap persyaratan baru, Anda tidak akan memerlukan jumlah kasus uji yang eksponensial juga. Dalam contoh Anda, siklus TDD mungkin akan terlihat seperti ini:
Kemudian, mulailah dengan persyaratan ke-2:
Inilah hasilnya : ketika Anda menambahkan kasus uji untuk persyaratan / nomor kategori "n", Anda hanya perlu menambahkan tes untuk memastikan bahwa skor kategori "n-1" lebih tinggi daripada skor untuk kategori "n" . Anda tidak perlu menambahkan kasus uji untuk setiap kombinasi kategori 1, ..., n-1, karena tes yang telah Anda tulis sebelumnya akan memastikan bahwa skor kategori tersebut masih dalam urutan yang benar.
Jadi ini akan memberi Anda sejumlah kasus uji yang tumbuh kira-kira linier dengan jumlah persyaratan, tidak secara eksponensial.
sumber
Pertimbangkan menulis kelas yang melewati daftar kondisi yang telah ditentukan dan mengalikan skor saat ini dengan 2 untuk setiap cek yang berhasil.
Ini dapat diuji dengan sangat mudah, hanya dengan menggunakan beberapa tes yang diejek.
Kemudian Anda dapat menulis kelas untuk setiap kondisi dan hanya ada 2 tes untuk setiap kasus.
Saya tidak benar-benar memahami kasus penggunaan Anda, tetapi mudah-mudahan contoh ini akan membantu.
Anda akan melihat bahwa pengujian 2 kondisi Anda dengan cepat turun ke 4+ (kondisi 2 *). 20 jauh lebih sombong daripada 64. Dan jika Anda menambahkan satu lagi nanti, Anda tidak perlu mengubah APAPUN dari kelas yang ada (prinsip buka-tutup), jadi Anda tidak perlu menulis 64 tes baru, Anda hanya perlu untuk menambahkan kelas lain dengan 2 tes baru dan menyuntikkannya ke kelas ScoreBuilder Anda.
sumber
Anda harus mendefinisikan "sepadan". Masalah dengan skenario semacam ini adalah bahwa tes akan memiliki pengembalian manfaat yang semakin berkurang. Tentu saja tes pertama yang Anda tulis akan sangat bermanfaat. Itu dapat menemukan kesalahan yang jelas dalam prioritas dan bahkan hal-hal seperti kesalahan penguraian ketika mencoba untuk memecah kata-kata.
Tes kedua akan sia-sia karena mencakup jalur yang berbeda melalui kode, mungkin memeriksa hubungan prioritas lain.
Tes ke-63 mungkin tidak akan sia-sia karena itu adalah sesuatu yang Anda yakin 99,99% dicakup oleh logika kode Anda atau tes lain.
Pemahaman saya adalah cakupan 100% berarti semua jalur kode dijalankan. Ini tidak berarti Anda melakukan semua kombinasi aturan Anda, tetapi semua jalur yang berbeda yang dapat dihilangkan kode Anda (seperti yang Anda tunjukkan, beberapa kombinasi tidak dapat ada dalam kode). Tetapi karena Anda melakukan TDD, belum ada "kode" untuk memeriksa jalur. Surat proses akan mengatakan make all 63+.
Secara pribadi, saya menemukan cakupan 100% menjadi mimpi pipa. Selain itu, itu tidakagmatis. Tes unit ada untuk melayani Anda, bukan sebaliknya. Ketika Anda melakukan lebih banyak tes, Anda mendapatkan hasil yang semakin berkurang (kemungkinan bahwa tes mencegah bug + keyakinan bahwa kode tersebut benar). Tergantung pada apa kode Anda menentukan di mana pada skala geser Anda berhenti membuat tes. Jika kode Anda menjalankan reaktor nuklir, maka mungkin semua 63+ tes layak dilakukan. Jika kode Anda mengatur arsip musik Anda, maka Anda mungkin bisa mendapatkan lebih sedikit.
sumber
Saya berpendapat bahwa ini adalah kasus yang sempurna untuk TDD.
Anda memiliki serangkaian kriteria untuk diuji, dengan uraian logis dari kasus-kasus itu. Dengan asumsi Anda akan mengujinya sekarang atau nanti, tampaknya masuk akal untuk mengambil hasil yang diketahui dan membangunnya, memastikan Anda, pada kenyataannya, mencakup setiap aturan secara mandiri.
Plus, Anda bisa mencari tahu saat Anda pergi jika menambahkan aturan pencarian baru melanggar aturan yang ada. Jika Anda melakukan semua ini di akhir pengkodean, Anda mungkin menjalankan risiko lebih besar karena harus mengubah satu untuk memperbaikinya, yang merusak yang lain, yang melanggar yang lain ... Dan, Anda belajar saat Anda menerapkan aturan apakah desain Anda valid. atau perlu tweaker.
sumber
Saya bukan penggemar ketat menafsirkan cakupan pengujian 100% sebagai menulis spesifikasi terhadap setiap metode tunggal atau menguji setiap permutasi kode. Melakukan ini secara fanatik cenderung mengarah pada desain yang digerakkan oleh tes dari kelas Anda yang tidak merangkum logika bisnis dengan baik dan menghasilkan tes / spesifikasi yang umumnya tidak berarti dalam hal menggambarkan logika bisnis yang didukung. Sebagai gantinya, saya fokus pada penataan tes seperti aturan bisnis itu sendiri dan berusaha untuk melakukan setiap cabang kondisional dari kode dengan tes dengan harapan eksplisit bahwa tes mudah dimengerti oleh tester seperti umumnya kasus penggunaan akan dan benar-benar menggambarkan aturan bisnis yang diterapkan.
Dengan ide ini dalam pikiran, saya akan menguji unit menyeluruh 6 faktor peringkat Anda terdaftar dalam satu sama lain ditindaklanjuti dengan 2 atau 3 tes gaya integrasi yang memastikan Anda menggulung hasil Anda ke nilai peringkat keseluruhan yang diharapkan. Sebagai contoh, kasus # 1, Pencocokan Tepat pada Nama, saya akan memiliki setidaknya dua unit tes untuk menguji kapan tepatnya dan kapan tidak dan bahwa dua skenario mengembalikan skor yang diharapkan. Jika case sensitif, maka juga case untuk menguji "Pencocokan Tepat" vs. "pencocokan tepat" dan mungkin variasi input lainnya seperti tanda baca, spasi tambahan, dll. Juga mengembalikan skor yang diharapkan.
Setelah saya bekerja melalui semua faktor individu yang berkontribusi pada skor peringkat, saya pada dasarnya menganggap ini berfungsi dengan benar di tingkat integrasi dan fokus pada memastikan faktor-faktor gabungan mereka dengan benar berkontribusi pada skor peringkat akhir yang diharapkan.
Dengan asumsi kasus # 2 / # 3 dan # 4 / # 5 digeneralisasikan ke metode dasar yang sama, tetapi dengan melewati bidang yang berbeda, Anda hanya perlu menulis satu set unit test untuk metode yang mendasarinya dan menulis tes unit tambahan sederhana untuk menguji spesifik bidang (judul, nama, deskripsi, dll.) dan penilaian di anjak yang ditentukan, jadi ini lebih lanjut mengurangi redundansi keseluruhan upaya pengujian Anda.
Dengan pendekatan ini, pendekatan yang dijelaskan di atas mungkin akan menghasilkan 3 atau 4 unit tes pada kasus # 1, mungkin 10 spesifikasi pada beberapa / semua w / sinonim dicatat - ditambah 4 spesifikasi pada penilaian kasus # 2 - # 5 dan 2 yang benar ke 3 spesifikasi pada tanggal terakhir yang diperintahkan peringkat, kemudian 3 hingga 4 tes tingkat integrasi yang mengukur semua 6 kasus yang digabungkan dalam cara yang mungkin (lupakan kasus tepi yang tidak jelas untuk saat ini kecuali jika Anda melihat dengan jelas masalah dalam kode Anda yang perlu dilakukan untuk memastikan kondisi itu ditangani) atau memastikan tidak dilanggar / rusak oleh revisi nanti. Itu menghasilkan sekitar 25 atau lebih spesifikasi untuk menjalankan 100% dari kode yang ditulis (meskipun Anda tidak secara langsung memanggil 100% dari metode yang ditulis).
sumber
Saya tidak pernah menjadi penggemar cakupan tes 100%. Dalam pengalaman saya, jika ada sesuatu yang cukup sederhana untuk diuji dengan hanya satu atau dua kasus uji, maka itu cukup sederhana untuk jarang gagal. Ketika gagal, biasanya karena perubahan arsitektur yang memerlukan perubahan uji.
Yang sedang berkata, untuk persyaratan seperti Anda, saya selalu menguji unit secara menyeluruh, bahkan pada proyek pribadi di mana tidak ada yang membuat saya, karena itu adalah kasus ketika pengujian unit menghemat waktu dan kejengkelan Anda. Semakin banyak tes unit yang diperlukan untuk menguji sesuatu, semakin banyak tes unit waktu akan menghemat.
Itu karena Anda hanya bisa memegang begitu banyak hal di kepala Anda sekaligus. Jika Anda mencoba menulis kode yang berfungsi untuk 63 kombinasi berbeda, seringkali sulit untuk memperbaiki satu kombinasi tanpa merusak yang lain. Anda akhirnya menguji kombinasi lain secara manual berulang kali. Pengujian manual jauh lebih lambat, yang membuat Anda tidak ingin menjalankan kembali setiap kombinasi yang mungkin setiap kali Anda melakukan perubahan. Itu membuat Anda lebih mungkin melewatkan sesuatu, dan lebih cenderung membuang waktu untuk menempuh jalan yang tidak cocok untuk semua kasus.
Selain menghemat waktu dibandingkan dengan pengujian manual, ada ketegangan mental jauh lebih sedikit, yang membuatnya lebih mudah untuk fokus pada masalah yang dihadapi tanpa khawatir tentang memperkenalkan regresi secara tidak sengaja. Itu memungkinkan Anda bekerja lebih cepat dan lebih lama tanpa kelelahan. Menurut pendapat saya, manfaat kesehatan mental saja sepadan dengan biaya pengujian kode kompleks, bahkan jika itu tidak menghemat waktu Anda.
sumber