Saya sering bekerja dengan program yang sangat numerik / matematis, di mana hasil pasti dari suatu fungsi sulit diprediksi sebelumnya.
Dalam mencoba menerapkan TDD dengan kode semacam ini, saya sering menemukan bahwa menulis kode yang sedang diuji secara signifikan lebih mudah daripada menulis unit test untuk kode itu, karena satu-satunya cara saya tahu untuk menemukan hasil yang diharapkan adalah menerapkan algoritma itu sendiri (baik dalam kepala, di atas kertas, atau oleh komputer). Ini terasa salah, karena saya secara efektif menggunakan kode yang sedang diuji untuk memverifikasi unit test saya, bukan sebaliknya.
Adakah teknik yang dikenal untuk menulis unit test dan menerapkan TDD ketika hasil kode yang diuji sulit diprediksi?
Contoh kode (nyata) dengan hasil yang sulit diprediksi:
Sebuah fungsi weightedTasksOnTime
yang, diberikan sejumlah pekerjaan yang dilakukan per hari workPerDay
dalam kisaran (0, 24], waktu saat ini initialTime
> 0, dan daftar tugas taskArray
; masing-masing dengan waktu untuk menyelesaikan properti time
> 0, tanggal jatuh tempo due
, dan nilai penting importance
; pengembalian nilai yang dinormalisasi dalam rentang [0, 1] mewakili pentingnya tugas yang dapat diselesaikan sebelum due
tanggal mereka jika setiap tugas diselesaikan dalam urutan yang diberikan oleh taskArray
, mulai dari initialTime
.
Algoritme untuk mengimplementasikan fungsi ini relatif mudah: beralih pada tugas di taskArray
. Untuk setiap tugas, tambahkan time
ke initialTime
. Jika waktu baru < due
, tambahkan importance
ke akumulator. Waktu disesuaikan dengan workPerDay terbalik. Sebelum mengembalikan akumulator, bagi dengan jumlah kepentingan tugas untuk dinormalisasi.
function weightedTasksOnTime(workPerDay, initialTime, taskArray) {
let simulatedTime = initialTime
let accumulator = 0;
for (task in taskArray) {
simulatedTime += task.time * (24 / workPerDay)
if (simulatedTime < task.due) {
accumulator += task.importance
}
}
return accumulator / totalImportance(taskArray)
}
Saya percaya masalah di atas dapat disederhanakan, dengan tetap mempertahankan intinya, dengan menghapus workPerDay
dan persyaratan normalisasi, untuk memberikan:
function weightedTasksOnTime(initialTime, taskArray) {
let simulatedTime = initialTime
let accumulator = 0;
for (task in taskArray) {
simulatedTime += task.time
if (simulatedTime < task.due) {
accumulator += task.importance
}
}
return accumulator
}
Pertanyaan ini membahas situasi di mana kode yang diuji bukan implementasi ulang dari algoritma yang ada. Jika kode adalah implementasi ulang, secara intrinsik memiliki mudah untuk memprediksi hasil, karena implementasi algoritma yang dipercaya bertindak sebagai ramalan uji alami.
sumber
Jawaban:
Ada dua hal yang dapat Anda uji dalam kode yang sulit untuk diuji. Pertama, kasus-kasus yang merosot. Apa yang terjadi jika Anda tidak memiliki elemen dalam larik tugas Anda, atau hanya satu, atau dua tetapi satu melewati batas waktu, dll. Apa pun yang lebih sederhana daripada masalah Anda yang sebenarnya, tetapi masih masuk akal untuk menghitung secara manual.
Yang kedua adalah cek kewarasan. Ini adalah cek yang Anda lakukan di mana Anda tidak tahu apakah jawaban itu benar , tetapi Anda pasti tahu jika itu salah . Ini adalah hal-hal seperti waktu harus bergerak maju, nilai harus dalam kisaran yang masuk akal, persentase harus ditambah hingga 100, dll.
Ya, ini tidak sebagus tes penuh, tetapi Anda akan terkejut betapa sering Anda mengacaukan pemeriksaan kewarasan dan menurunkan kasus, yang mengungkapkan masalah dalam algoritma lengkap Anda.
sumber
Saya biasa menulis tes untuk perangkat lunak ilmiah dengan output yang sulit diprediksi. Kami banyak menggunakan Hubungan Metamorf. Pada dasarnya ada hal-hal yang Anda ketahui tentang bagaimana perangkat lunak Anda harus bersikap bahkan jika Anda tidak tahu output numerik yang tepat.
Contoh yang mungkin untuk kasus Anda: jika Anda mengurangi jumlah pekerjaan yang dapat Anda lakukan setiap hari, maka jumlah total pekerjaan yang dapat Anda lakukan akan tetap sama, tetapi kemungkinan menurun. Jadi jalankan fungsi untuk sejumlah nilai
workPerDay
dan pastikan relasi tersebut berlaku.sumber
Jawaban lain memiliki ide bagus untuk mengembangkan tes untuk kasus tepi atau kesalahan. Bagi yang lain, menggunakan algoritma itu sendiri tidak ideal (jelas) tetapi masih bermanfaat.
Ini akan mendeteksi jika algoritma (atau data tergantung pada) telah berubah
Jika perubahan itu merupakan kecelakaan, Anda dapat memutar kembali komit. Jika perubahan itu disengaja, Anda perlu mengunjungi kembali unit test.
sumber
Cara yang sama Anda menulis unit test untuk jenis kode lain:
Kecuali jika kode Anda melibatkan beberapa elemen acak atau tidak deterministik (artinya tidak akan menghasilkan output yang sama dengan input yang sama), itu dapat diuji unit.
Hindari efek samping, atau fungsi yang dipengaruhi oleh kekuatan luar. Fungsi murni lebih mudah untuk diuji.
sumber
Unless your code involves some random element
Kuncinya di sini adalah untuk membuat generator angka acak Anda menjadi ketergantungan yang disuntikkan, sehingga Anda dapat menggantinya dengan generator angka yang memberikan hasil persis seperti yang Anda inginkan. Ini memungkinkan Anda untuk menguji lagi secara akurat - menghitung angka yang dihasilkan sebagai parameter input juga.not deterministic (i.e. it won't produce the same output given the same input)
Karena tes unit harus dimulai dari situasi yang terkendali , itu hanya dapat bersifat non-deterministik jika memiliki elemen acak - yang kemudian dapat Anda injeksi. Saya tidak bisa memikirkan kemungkinan lain di sini.if(x == x)
, itu adalah perbandingan yang tidak berguna. Anda memerlukan dua hasil Anda ( aktual : berasal dari kode; diharapkan : berasal dari pengetahuan eksternal Anda) agar tidak tergantung satu sama lain.Pembaruan karena komentar yang diposting
Jawaban asli dihapus demi singkatnya - Anda dapat menemukannya di riwayat edit.
Pertama, TL; DR untuk menghindari jawaban yang panjang:
Masalah utama di sini adalah bahwa Anda tidak membuat pemisahan antara pelanggan dan pengembang (dan analis - meskipun peran itu dapat diwakili oleh pengembang juga).
Anda perlu membedakan antara menguji kode, dan menguji persyaratan bisnis.
Sebagai contoh, pelanggan menginginkannya bekerja seperti ini . Namun, pengembang salah paham, dan dia menulis kode yang melakukan itu .
Oleh karena itu pengembang akan menulis unit test yang menguji apakah [itu] berfungsi seperti yang diharapkan. Jika ia mengembangkan aplikasi dengan benar, pengujian unitnya akan berlalu meskipun aplikasi tidak melakukan [ini] , yang diharapkan pelanggan.
Jika Anda ingin menguji harapan pelanggan (persyaratan bisnis), itu perlu dilakukan dalam langkah terpisah (dan kemudian).
Alur kerja pengembangan sederhana untuk menunjukkan kepada Anda kapan tes ini harus dijalankan:
Anda mungkin bertanya-tanya apa gunanya melakukan dua tes terpisah ketika pelanggan dan pengembang adalah satu dan sama. Karena tidak ada "hand off" dari pengembang ke pelanggan, tes dijalankan satu demi satu, tetapi mereka masih langkah terpisah.
Jika Anda ingin menguji apakah algoritme Anda sendiri benar, itu bukan bagian dari pekerjaan pengembang . Itu adalah keprihatinan pelanggan, dan pelanggan akan menguji ini dengan menggunakan aplikasi.
Sebagai wirausaha dan akademis, Anda mungkin kehilangan perbedaan penting di sini, yang menyoroti tanggung jawab yang berbeda.
sumber
Pengujian Properti
Kadang-kadang fungsi matematika lebih baik dilayani oleh "Pengujian Properti" daripada oleh pengujian unit berbasis contoh tradisional. Misalnya, bayangkan Anda sedang menulis unit test untuk sesuatu seperti fungsi integer "multiply". Sementara fungsi itu sendiri mungkin tampak sangat sederhana, jika itu satu-satunya cara untuk memperbanyak, bagaimana Anda mengujinya secara menyeluruh tanpa logika dalam fungsi itu sendiri? Anda bisa menggunakan tabel raksasa dengan input / output yang diharapkan, tetapi ini terbatas dan rawan kesalahan.
Dalam kasus ini, Anda dapat menguji properti fungsi yang diketahui, alih-alih mencari hasil yang diharapkan spesifik. Untuk penggandaan, Anda mungkin tahu bahwa mengalikan angka negatif dan angka positif harus menghasilkan angka negatif, dan bahwa mengalikan dua angka negatif harus menghasilkan angka positif, dll. Menggunakan nilai acak dan kemudian memeriksa bahwa properti ini dipertahankan untuk semua nilai tes adalah cara yang baik untuk menguji fungsi-fungsi tersebut. Anda biasanya perlu menguji lebih dari satu properti, tetapi Anda sering dapat mengidentifikasi serangkaian properti terbatas yang bersama-sama memvalidasi perilaku yang benar dari suatu fungsi tanpa harus mengetahui hasil yang diharapkan untuk setiap kasus.
Salah satu pengantar terbaik untuk Pengujian Properti yang pernah saya lihat adalah yang ini di F #. Semoga sintaksisnya tidak menjadi halangan untuk memahami penjelasan teknik tersebut.
sumber
Sangat menggoda untuk menulis kode dan kemudian melihat apakah hasilnya "terlihat benar", tetapi, karena Anda memiliki intuisi yang benar, itu bukan ide yang baik.
Ketika algoritma sulit, Anda dapat melakukan sejumlah hal untuk membuat perhitungan manual hasilnya lebih mudah.
Gunakan Excel Siapkan spreadsheet yang melakukan sebagian atau semua perhitungan untuk Anda. Jaga agar tetap sederhana sehingga Anda dapat melihat langkah-langkahnya.
Bagi metode Anda menjadi metode yang lebih kecil yang dapat diuji, masing-masing dengan tes mereka sendiri. Saat Anda yakin bagian yang lebih kecil berfungsi, gunakan untuk mengerjakan langkah selanjutnya secara manual.
Gunakan properti agregat untuk memeriksa kewarasan. Misalnya, Anda memiliki kalkulator probabilitas; Anda mungkin tidak tahu seperti apa hasil masing-masing, tetapi Anda tahu mereka semua harus menambahkan hingga 100%.
Kasar. Tulis program yang menghasilkan semua hasil yang mungkin, dan periksa tidak ada yang lebih baik dari yang dihasilkan oleh algoritma Anda.
sumber
TL; DR
Buka bagian "pengujian komparatif" untuk mendapatkan saran yang tidak ada dalam jawaban lain.
Awal
Mulailah dengan menguji kasus-kasus yang harus ditolak oleh algoritma (nol atau negatif
workPerDay
, misalnya) dan kasus-kasus yang sepele (misalnyatasks
array kosong ).Setelah itu, Anda ingin menguji kasus yang paling sederhana terlebih dahulu. Untuk
tasks
input, kita perlu menguji panjang yang berbeda; harus cukup untuk menguji elemen 0, 1 dan 2 (2 termasuk dalam kategori "banyak" untuk tes ini).Jika Anda dapat menemukan input yang dapat dihitung secara mental, itu awal yang baik. Suatu teknik yang kadang-kadang saya gunakan adalah mulai dari hasil yang diinginkan dan bekerja kembali (dalam spesifikasi) ke input yang seharusnya menghasilkan hasil itu.
Pengujian komparatif
Kadang-kadang hubungan output ke input tidak jelas, tetapi Anda memiliki hubungan yang dapat diprediksi antara output yang berbeda ketika satu input diubah. Jika saya telah memahami contoh dengan benar, maka menambahkan tugas (tanpa mengubah input lain) tidak akan pernah meningkatkan proporsi pekerjaan yang dilakukan tepat waktu, sehingga kami dapat membuat tes yang memanggil fungsi dua kali - sekali dengan dan sekali tanpa tugas tambahan - dan menegaskan ketimpangan antara dua hasil.
Kekalahan
Kadang-kadang saya harus menggunakan komentar panjang yang menunjukkan hasil yang dihitung dengan tangan dalam langkah-langkah yang sesuai dengan spesifikasi (komentar seperti itu biasanya lebih panjang daripada test case). Kasus terburuk adalah ketika Anda harus mempertahankan kompatibilitas dengan implementasi sebelumnya dalam bahasa yang berbeda atau untuk lingkungan yang berbeda. Terkadang Anda hanya perlu memberi label data pengujian dengan sesuatu seperti
/* derived from v2.6 implementation on ARM system */
. Itu tidak terlalu memuaskan, tetapi dapat diterima sebagai uji kesetiaan saat porting, atau sebagai penopang jangka pendek.Pengingat
Atribut yang paling penting dari tes adalah keterbacaannya - jika input dan outputnya buram bagi pembaca, maka tes tersebut memiliki nilai yang sangat rendah, tetapi jika pembaca dibantu untuk memahami hubungan di antara mereka, maka tes tersebut melayani dua tujuan.
Jangan lupa untuk menggunakan "kira-kira sama" untuk hasil yang tidak tepat (misalnya titik-mengambang).
Hindari pengujian berlebihan - hanya tambahkan tes jika mencakup sesuatu (seperti nilai batas) yang tidak dicapai oleh tes lain.
sumber
Tidak ada yang sangat istimewa tentang fungsi sulit untuk diuji ini. Hal yang sama berlaku untuk kode yang menggunakan antarmuka eksternal (katakanlah, REST API dari aplikasi pihak ke-3 yang tidak di bawah kendali Anda dan tentu saja tidak dapat diuji oleh suite pengujian Anda, atau menggunakan perpustakaan pihak ke-3 di mana Anda tidak yakin dengan format byte yang tepat dari nilai pengembalian).
Ini adalah pendekatan yang cukup valid untuk menjalankan algoritma Anda untuk beberapa input yang masuk akal, melihat apa yang dilakukannya, memastikan bahwa hasilnya benar, dan merangkum input dan hasilnya sebagai test case. Anda dapat melakukan ini untuk beberapa kasus dan karenanya mendapatkan beberapa sampel. Cobalah untuk membuat parameter input berbeda mungkin. Dalam kasus panggilan API eksternal, Anda akan melakukan beberapa panggilan terhadap sistem nyata, melacaknya dengan beberapa alat, dan kemudian mengejeknya ke dalam unit test Anda untuk melihat bagaimana program Anda bereaksi - yang sama dengan hanya mengambil beberapa menjalankan kode perencanaan tugas Anda, memverifikasinya dengan tangan, dan kemudian meng-hardcoding hasilnya dalam pengujian Anda.
Kemudian, jelas, bawa kasus tepi seperti (dalam contoh Anda) daftar tugas kosong; hal-hal seperti itu.
Test suite Anda mungkin tidak akan sebagus metode di mana Anda dapat dengan mudah memprediksi hasil; tetapi masih 100% lebih baik daripada tidak ada test suite (atau hanya tes asap).
Jika masalah Anda, meskipun, adalah bahwa Anda merasa sulit untuk memutuskan apakah hasilnya adalah benar, maka itu adalah masalah yang sama sekali berbeda. Misalnya, Anda memiliki metode yang mendeteksi apakah angka besar yang sewenang-wenang adalah prima. Anda tidak dapat melemparkan angka acak ke sana dan kemudian hanya "melihat" jika hasilnya benar (dengan asumsi Anda tidak dapat menentukan keunggulan di kepala Anda atau di selembar kertas). Dalam hal ini, memang ada sedikit yang bisa Anda lakukan - Anda harus mendapatkan hasil yang diketahui (yaitu, beberapa bilangan prima besar), atau mengimplementasikan fungsionalitas dengan algoritma yang berbeda (mungkin bahkan tim yang berbeda - NASA tampaknya menyukai itu) dan berharap bahwa jika salah satu implementasi bermasalah, setidaknya bug tidak mengarah ke hasil yang salah sama.
Jika ini adalah kasus biasa bagi Anda, maka Anda harus bicara keras dengan insinyur kebutuhan Anda. Jika mereka tidak dapat merumuskan persyaratan Anda dengan cara yang mudah (atau mungkin) untuk memeriksa Anda, lalu kapan Anda tahu apakah Anda sudah selesai?
sumber
Jawaban lain baik, jadi saya akan mencoba untuk mencapai beberapa poin yang secara kolektif mereka lewatkan sejauh ini.
Saya telah menulis (dan benar-benar diuji) perangkat lunak untuk melakukan pemrosesan gambar menggunakan Radar Aperture Sintetis (SAR). Ini ilmiah / numerik di alam (ada banyak geometri, fisika, dan matematika yang terlibat).
Beberapa tips (untuk pengujian ilmiah / numerik umum):
1) Gunakan invers. Apa
fft
of[1,2,3,4,5]
? Tidak ada ide. Apaifft(fft([1,2,3,4,5]))
? Seharusnya[1,2,3,4,5]
(atau dekat dengan itu, kesalahan floating point mungkin muncul). Hal yang sama berlaku untuk case 2D.2) Gunakan pernyataan yang dikenal. Jika Anda menulis fungsi determinan, mungkin sulit untuk mengatakan apa determinannya dari matriks 100x100 acak. Tapi Anda tahu bahwa penentu matriks identitas adalah 1, bahkan jika itu 100x100. Anda juga tahu bahwa fungsi tersebut harus mengembalikan 0 pada matriks yang tidak dapat dibalik (seperti 100x100 penuh dari semua 0s).
3) Gunakan konfirmasi kasar, bukan konfirmasi yang tepat . Saya menulis beberapa kode untuk pemrosesan SAR yang akan mendaftarkan dua gambar dengan menghasilkan titik pengikat yang membuat pemetaan antara gambar dan kemudian melakukan lungsin di antara mereka untuk membuatnya cocok. Itu bisa mendaftar pada tingkat sub-pixel. A priori, sulit untuk mengatakan apa -apa tentang bagaimana pendaftaran dua gambar akan terlihat. Bagaimana Anda bisa mengujinya? Hal-hal seperti:
karena Anda hanya dapat mendaftar pada bagian yang tumpang tindih, gambar yang terdaftar harus lebih kecil atau sama dengan gambar terkecil Anda, dan juga:
karena gambar yang didaftarkan ke dirinya sendiri harus TUTUP untuk dirinya sendiri, tetapi Anda mungkin mengalami sedikit lebih banyak dari kesalahan floating point karena algoritma yang ada, jadi cukup periksa setiap piksel dalam +/- 5% dari rentang piksel yang dapat diambil (0-255 berwarna abu-abu, umum dalam pemrosesan gambar). Hasil setidaknya harus berukuran sama dengan input.
Anda bahkan dapat hanya merokok tes (mis. Panggilan itu dan pastikan itu tidak crash). Secara umum, teknik ini lebih baik untuk tes yang lebih besar di mana hasil akhirnya tidak dapat (dengan mudah) dihitung secara apriori untuk menjalankan tes.
4) Gunakan ATAU MENYIMPAN seed number acak untuk RNG Anda.
Berjalan memang harus direproduksi. Adalah salah, bagaimanapun, bahwa satu-satunya cara untuk mendapatkan proses yang dapat direproduksi adalah dengan menyediakan benih khusus untuk generator angka acak. Terkadang pengujian keacakan bernilai. Saya telah melihat / mendengar tentang bug dalam kode ilmiah yang muncul dalam kasus degenerasi yang dihasilkan secara acak (dalam algoritma yang rumit mungkin sulit untuk melihat apa kasus degenerasi itu)). Alih-alih selalu memanggil fungsi Anda dengan seed yang sama, hasilkan seed acak, lalu gunakan seed itu, dan catat nilai seed tersebut. Dengan begitu setiap proses memiliki seed acak berbeda, tetapi jika Anda mendapatkan crash, Anda dapat menjalankan kembali hasilnya dengan menggunakan seed yang telah Anda login ke debug. Saya sebenarnya telah menggunakan ini dalam praktek dan itu menghancurkan bug, jadi saya pikir saya akan menyebutkannya. Memang ini hanya terjadi sekali, dan saya yakin itu tidak selalu layak dilakukan, jadi gunakan teknik ini dengan bijaksana. Acak dengan benih yang sama selalu aman. Kekurangan (bukan hanya menggunakan seed yang sama sepanjang waktu): Anda harus mencatat uji coba Anda. Terbalik: Koreksi dan bug nuking.
Kasus khusus Anda
1) Uji bahwa kosong
taskArray
mengembalikan 0 (dikenal menegaskan).2) Menghasilkan input acak sehingga
task.time > 0
,task.due > 0
, dantask.importance > 0
untuk semuatask
s, dan menegaskan hasilnya lebih besar dari0
(menegaskan kasar, masukan acak) . Anda tidak perlu menjadi gila dan menghasilkan benih acak, algoritma Anda tidak cukup kompleks untuk menjaminnya. Ada sekitar 0 kesempatan itu akan terbayar: tetap uji sederhana.3) Uji jika
task.importance == 0
untuk semuatask
s, maka hasilnya adalah0
(dikenal dengan tegas)4) Jawaban lain menyentuh ini, tetapi mungkin penting untuk kasus khusus Anda : Jika Anda membuat API untuk dikonsumsi oleh pengguna di luar tim Anda, Anda perlu menguji kasus yang merosot. Misalnya, jika
workPerDay == 0
, pastikan Anda melempar kesalahan indah yang memberi tahu pengguna bahwa input tidak valid. Jika Anda tidak membuat API, dan itu hanya untuk Anda dan tim Anda, Anda mungkin dapat melewati langkah ini, dan hanya menolak untuk memanggilnya dengan case degenerate.HTH.
sumber
Menggabungkan pengujian asersi ke dalam unit test unit Anda untuk pengujian berbasis properti dari algoritma Anda. Selain menulis unit test yang memeriksa output spesifik, tes menulis dirancang untuk gagal dengan memicu kegagalan pernyataan dalam kode utama.
Banyak algoritma mengandalkan bukti kebenarannya pada mempertahankan properti tertentu di seluruh tahapan algoritma. Jika Anda dapat memeriksa properti ini secara masuk akal dengan melihat output dari suatu fungsi, pengujian unit saja sudah cukup untuk menguji properti Anda. Jika tidak, pengujian berbasis pernyataan memungkinkan Anda menguji bahwa suatu implementasi mempertahankan properti setiap kali algoritma mengasumsikannya.
Pengujian berbasis pernyataan akan mengekspos kekurangan algoritma, bug pengkodean, dan kegagalan implementasi karena masalah seperti ketidakstabilan numerik. Banyak bahasa memiliki mekanisme menghapus pernyataan pada waktu kompilasi atau sebelum kode ditafsirkan sehingga ketika dijalankan dalam mode produksi pernyataan tersebut tidak dikenakan penalti kinerja. Jika kode Anda lulus pengujian unit tetapi gagal pada kasus nyata, Anda dapat mengaktifkan kembali pernyataan sebagai alat debugging.
sumber
Beberapa jawaban lain di sini sangat bagus:
... Saya akan menambahkan beberapa taktik lain:
Dekomposisi memungkinkan Anda memastikan komponen algoritme Anda melakukan apa yang Anda harapkan. Dan dekomposisi yang "baik" memungkinkan Anda juga memastikan bahwa keduanya direkatkan dengan benar. Sebuah besar dekomposisi generalisasi dan menyederhanakan algoritma untuk sejauh yang Anda bisa memprediksi hasil (dari disederhanakan, algoritma generik (s)) dengan tangan cukup baik untuk menulis tes menyeluruh.
Jika Anda tidak dapat menguraikan sejauh itu, buktikan algoritma di luar kode dengan cara apa pun yang cukup untuk memuaskan Anda dan rekan kerja, pemangku kepentingan, dan pelanggan Anda. Dan kemudian, cukup dekomposisi untuk membuktikan implementasi Anda cocok dengan desain.
sumber
Ini mungkin tampak seperti jawaban idealis tetapi membantu mengidentifikasi berbagai jenis pengujian.
Jika jawaban ketat penting untuk implementasi maka contoh dan jawaban yang diharapkan benar-benar harus disediakan dalam persyaratan yang menggambarkan algoritma. Persyaratan ini harus ditinjau kelompok dan jika Anda tidak mendapatkan hasil yang sama, alasannya perlu diidentifikasi.
Sekalipun Anda berperan sebagai analis dan juga pelaksana, Anda harus benar-benar membuat persyaratan dan memeriksanya jauh sebelum Anda menulis tes unit, jadi dalam hal ini Anda akan mengetahui hasil yang diharapkan dan dapat menulis tes sesuai dengan itu.
Di sisi lain, jika ini adalah bagian yang Anda laksanakan yang bukan bagian dari logika bisnis atau mendukung jawaban logika bisnis, maka tidak masalah untuk menjalankan tes untuk melihat apa hasilnya dan kemudian memodifikasi tes yang diharapkan hasil itu. Hasil akhir sudah diperiksa terhadap persyaratan Anda sehingga jika mereka benar maka semua kode yang memberi makan hasil akhir harus benar secara numerik dan pada saat itu tes unit Anda lebih untuk mendeteksi kasus kegagalan tepi dan perubahan refactoring di masa depan daripada untuk membuktikan bahwa diberikan algoritma menghasilkan hasil yang benar.
sumber
Saya pikir itu dapat diterima pada kesempatan untuk mengikuti proses:
Ini adalah pendekatan yang masuk akal dalam situasi apa pun di mana memeriksa kebenaran jawaban dengan tangan lebih mudah daripada menghitung jawaban dengan tangan dari prinsip pertama.
Saya tahu orang-orang yang menulis perangkat lunak untuk merender halaman yang dicetak, dan memiliki tes yang memeriksa apakah piksel yang tepat sudah diatur pada halaman yang dicetak. Satu-satunya cara yang waras untuk melakukannya adalah dengan menulis kode untuk membuat halaman, memeriksa dengan mata bahwa itu terlihat bagus, dan kemudian menangkap hasilnya sebagai tes regresi untuk rilis mendatang.
Hanya karena Anda membaca di sebuah buku yang mendorong metodologi tertentu untuk menulis kasus ujian terlebih dahulu, tidak berarti Anda harus selalu melakukannya dengan cara itu. Aturan ada untuk dilanggar.
sumber
Jawaban lain jawaban sudah memiliki teknik untuk apa tes tampak ketika hasil spesifik tidak dapat ditentukan di luar fungsi yang diuji.
Apa yang saya lakukan sebagai tambahan yang belum saya temukan dalam jawaban lain adalah untuk membuat tes secara otomatis dengan beberapa cara:
Misalnya, jika fungsi tersebut masing-masing mengambil tiga parameter dengan rentang input yang diizinkan [-1,1], uji semua kombinasi dari setiap parameter, {-2, -1,01, -1, -0,99, -0,5, -0,01, -0,01, 0,0,01 , 0,5,0,99,1,1,01,2, beberapa lebih acak dalam (-1,1)}
Singkatnya: Terkadang kualitas yang buruk dapat disubsidi oleh kuantitas.
sumber