Mempertimbangkan metode untuk secara acak mengocok elemen dalam array. Bagaimana anda akan menulis yang sederhana namun kuat unit test untuk memastikan bahwa ini bekerja?
I've datang dengan dua ide-ide, yang keduanya memiliki kelemahan terlihat:
Mempertimbangkan kedua fungsi yang mensimulasikan gulungan dadu dan kembali nomor acak. Bagaimana anda akan menguji fungsi ini? Bagaimana cara menguji bahwa fungsi...
I'm mencari jawaban menawarkan wawasan ke dalam pengujian tidak hanya contoh-contoh ini, tetapi unsur-unsur acak kode pada umumnya. Adalah unit tes bahkan solusi yang tepat di sini? Jika tidak, seperti apa tes?
Hanya untuk memudahkan semua orang's mind I'm tidak tulisan saya sendiri nomor acak generator.
Saya don't pikir unit tes adalah alat yang tepat untuk menguji keacakan. Unit test harus memanggil metode dan menguji kembali nilai (atau keadaan objek) terhadap nilai yang diharapkan. Masalah dengan pengujian keacakan yang ada isn't suatu nilai yang diharapkan bagi sebagian besar dari hal-hal yang anda'd ingin menguji. Anda dapat menguji dengan diberikan benih, tapi itu hanya tes pengulangan. Itu doesn't memberikan cara untuk mengukur bagaimana random distribusi, atau jika itu's bahkan acak.
Untungnya, ada banyak dari uji statistik yang dapat anda jalankan, seperti Diehard Baterai Tes Keacakan. Lihat juga:
I've melihat winzip digunakan sebagai alat untuk mengukur keteracakan file dari nilai sebelum (jelas, semakin kecil hal ini dapat memampatkan file yang kurang acak itu).
Untuk pertanyaan pertama saya akan membangun palsu kelas yang anda makan urutan angka acak yang anda tahu hasil dari algoritma anda. Dengan cara itu anda pastikan algoritma anda membangun di atas anda acak fungsi bekerja. Jadi, sesuatu di sepanjang baris:
Random r = new RandomStub([1,3,5,3,1,2]);
r.random(); //returns 1
r.random(); //returns 3
...
Untuk unit tes anda harus menambahkan sebuah tes yang berjalan beberapa kali dan menegaskan bahwa hasil
2
datang antara 10% dan 20% (1/6 = 16.67%) dari waktu yang diberikan bahwa anda berguling 1000 kali).Seberapa sering anda harapkan array diurutkan asli sorting? Mengurutkan beberapa ratus kali dan menegaskan bahwa hanya x% dari waktu pengurutan tidak berubah.
Ini sebenarnya sudah merupakan integrasi tes, anda menguji algoritma yang bersama-sama dengan fungsi random. Setelah anda menggunakan real acak fungsi anda dapat't mendapatkan jauh dengan satu uji coba lagi.
Dari pengalaman (saya menulis algoritma genetik) saya akan mengatakan menggabungkan unit tes algoritma, distribusi tes acak fungsi dan uji integrasi adalah cara untuk pergi.
Aspek PRNGs yang tampaknya lupa tentang adalah bahwa semua sifat-sifat statistik di alam: anda dapat't mengharapkan yang menyeret sebuah array akan menghasilkan permutasi yang berbeda dari yang anda mulai dengan. Pada dasarnya, jika anda menggunakan normal PRNG, satu-satunya hal yang anda're dijamin adalah bahwa hal itu doesn't menggunakan pola sederhana (mudah-mudahan) dan bahwa hal itu bahkan distribusi di antara angka-angka itu kembali.
A proper test untuk PRNG akan melibatkan berjalan setidaknya 100 kali dan kemudian memeriksa distribusi output (yang merupakan jawaban langsung untuk pertanyaan kedua).
Jawaban untuk pertanyaan pertama adalah hampir sama: menjalankan tes sekitar 100 kali dengan {1, 2, ..., n} dan menghitung berapa kali masing-masing elemen telah di masing-masing posisi. Mereka semua harus kira-kira sama jika shuffle metode apapun yang baik.
Sebuah masalah yang sama sekali berbeda adalah cara untuk menguji kriptografi-kelas PRNGs. Ini adalah masalah di mana anda mungkin tidak't tinggal, kecuali jika anda benar-benar tahu apa yang anda lakukan. Orang-orang telah dikenal untuk hancurkan (baca: buka bencana lubang dalam) baik kriptografi dengan hanya beberapa 'optimasi' atau sepele suntingan.
EDIT: saya telah benar-benar membaca pertanyaan, atas jawabannya dan saya sendiri. Sementara poin yang saya buat masih berdiri, aku akan kedua Ruu Kadal's jawaban. Unit tes Boolean di alam mereka - mereka gagal, atau mereka berhasil, dan karena itu tidak cocok untuk pengujian "bagaimana baik" ini adalah sifat dari sebuah PRNG (atau menggunakan metode PRNG), karena setiap jawaban atas pertanyaan ini akan menjadi kuantitatif, daripada kutub.
Biarkan berjalan beberapa kali dan memvisualisasikan data anda.
Berikut ini's contoh shuffle dari Coding Horor, anda dapat melihat bahwa algoritma adalah OK atau tidak:
It's mudah untuk melihat bahwa setiap item adalah kembali setidaknya sekali (batas OK) dan bahwa distribusi adalah OK.
Ada dua bagian untuk ini: pengujian pengacakan dan pengujian hal-hal yang menggunakan pengacakan.
Pengujian pengacakan adalah relatif mudah. Anda memeriksa bahwa periode random number generator adalah seperti yang anda harapkan untuk menjadi (untuk beberapa sampel menggunakan beberapa agak acak-biji, dalam beberapa ambang batas) dan bahwa distribusi output lebih besar ukuran sampel seperti yang anda harapkan untuk menjadi (hanya beberapa ambang batas).
Pengujian hal-hal yang menggunakan pengacakan yang terbaik adalah dilakukan dengan deterministik pseudo-random number generator. Karena output dari pengacakan ini diketahui berdasarkan pada benih (input), maka anda dapat unit tes normal berdasarkan masukan-masukan yang lebih baik dari hasil yang diharapkan. Jika anda RNG adalah not deterministik, kemudian pura-pura itu dengan salah satu yang deterministik (atau hanya tidak acak). Uji pengacakan dalam isolasi dari kode yang mengkonsumsi itu.
Anda dapat bergantung pada secure random number generator
Saya hanya punya pikiran mengerikan: anda're tidak menulis sendiri random number generator anda?
Dengan asumsi anda're tidak, maka anda harus tes kode bahwa anda bertanggung jawab untuk, bukan orang lain's kode (seperti SecureRandom
implementasi untuk anda framework).
Menguji kode anda
Untuk menguji bahwa kode anda merespon dengan benar, itu adalah normal untuk menggunakan visibilitas rendah metode untuk menghasilkan angka acak sehingga dapat dengan mudah diganti oleh unit test kelas. Metode ini ditimpa efektif mengolok-olok keluar nomor acak generator dan memberi anda kontrol penuh atas apa yang dihasilkan dan kapan. Akibatnya anda dapat sepenuhnya menggunakan kode yang merupakan tujuan dari pengujian unit.
Jelas anda akan memeriksa edge kondisi dan memastikan bahwa menyeret berlangsung persis seperti yang anda algoritma perintah yang diberikan sesuai input.
Pengujian secure random number generator
Jika anda tidak yakin bahwa secure random number generator untuk bahasa anda tidak benar-benar acak atau kereta (termasuk keluar dari jangkauan nilai-nilai, dll), maka anda perlu untuk melakukan analisis statistik rinci dari output lebih dari beberapa ratus juta iterasi. Plot frekuensi terjadinya setiap nomor dan harus muncul dengan probabilitas yang sama. Jika hasil condong salah satu cara atau yang lain anda harus melaporkan temuan kerangka desainer. Mereka pasti akan tertarik dalam memperbaiki masalah secure random number generator adalah dasar untuk banyak algoritma enkripsi.
Umum pointer I've ditemukan berguna ketika berhadapan dengan kode yang mengambil secara acak input: Periksa edge kasus-kasus yang diharapkan keacakan (max dan min nilai-nilai, dan max+1 dan min-1 nilai jika berlaku). Periksa tempat (pada, di atas, dan bawah), dimana angka-angka yang memiliki titik infleksi (yaitu -1, 0, 1, atau lebih besar dari 1, kurang dari 1 dan non-negatif untuk kasus-kasus di mana pecahan nilai yang mungkin mengacaukan fungsi). Memeriksa beberapa tempat yang benar-benar di luar diperbolehkan input. Memeriksa beberapa kasus yang khas. Anda juga dapat menambahkan masukan acak, tapi untuk unit tes yang memiliki efek samping yang tidak diinginkan yang sama nilai isn't diuji setiap kali test run (benih pendekatan ini dapat bekerja meskipun, tes pertama 1.000 angka acak dari benih S atau somesuch).
Untuk pengujian output dari fungsi acak, hal ini penting untuk mengidentifikasi tujuan. Dalam kasus kartu, adalah tujuan untuk menguji keseragaman 0-1 random generator, untuk menentukan apakah semua 52 kartu muncul di hasil, atau untuk beberapa tujuan lainnya (mungkin semua dari daftar ini dan banyak lagi)?
Dalam contoh khusus ini, anda harus mengasumsikan anda nomor acak generator buram (hanya seperti itu doesn't masuk akal untuk unit test OS syscall atau malloc - kecuali anda menulis Os). Ini mungkin berguna untuk mengukur random number generator, tapi tujuan anda isn't untuk menulis random generator, hanya untuk melihat bahwa anda mendapatkan 52 kartu masing-masing waktu, dan bahwa mereka mengubah urutan.
Yang's a long way mengatakan bahwa ada benar-benar dua tes tugas-tugas berikut: pengujian yang RNG menghasilkan distribusi yang tepat, dan memeriksa bahwa anda kartu shuffle kode ini menggunakan RNG untuk menghasilkan acak hasil. Jika anda menulis RNG, menggunakan analisis statistik untuk membuktikan distribusi anda, jika anda're menulis kartu shuffler, pastikan ada 52 non-berulang-ulang kartu di masing-masing output (it's lebih baik untuk kasus uji dengan inspeksi yang anda're menggunakan RNG).
Untuk menguji bahwa sumber nomor acak menghasilkan sesuatu yang setidaknya memiliki penampilan keacakan, saya akan memiliki tes yang menghasilkan cukup besar urutan dari byte, mereka menulis ke berkas sementara, dan kemudian keluar untuk Fourmilab's ent tool. Memberikan tht-t (singkat) switch sehingga akan menghasilkan mudah-untuk-parse CSV. Kemudian memeriksa berbagai nomor untuk melihat bahwa mereka adalah "baik."
Untuk memutuskan apa angka-angka yang baik, gunakan diketahui sumber keacakan untuk mengkalibrasi tes anda. Tes harus hampir selalu melewati ketika diberikan baik set nomor acak. Karena bahkan benar-benar acak urutan memiliki kemungkinan menghasilkan urutan yang muncul untuk menjadi non-acak, anda dapat't mendapatkan tes yang tertentu untuk lulus. Anda hanya memilih ambang batas yang membuat hal ini tidak mungkin bahwa urutan acak akan menyebabkan kegagalan tes. Isn't keacakan menyenangkan?
Catatan: Anda tidak dapat menulis sebuah tes yang menunjukkan bahwa PRNG menghasilkan "random" urutan. Anda hanya bisa menulis tes itu, jika melewati, menunjukkan beberapa kemungkinan bahwa urutan yang dihasilkan oleh PRNG adalah "acak." Selamat datang sukacita keacakan!
Kasus 1: Pengujian shuffle:
Pertimbangkan sebuah Array [0, 1, 2, 3, 4, 5], shuffle itu, apa yang bisa salah? Hal-hal biasa: a) tidak ada shuffle sama sekali, b) menyeret 1-5 tapi tidak 0, menyeret 0-4 tapi tidak 5, menyeret, dan selalu menghasilkan pola yang sama, ...
Salah satu tes untuk menangkap mereka semua:
Shuffle 100 kali, tambahkan nilai-nilai di setiap slot. Jumlah slot masing-masing harus sama untuk masing-masing slot. Avg/Stddev dapat dihitung. (5+0)/2=2.5, 100*2.5 = 25. Nilai yang diharapkan adalah sekitar 25, misalnya.
Jika nilai berada di luar jangkauan, ada kemungkinan kecil bahwa anda punya negatif palsu. Anda dapat menghitung, seberapa besar kesempatan itu. Ulangi tes. Serta tentu saja ada kemungkinan kecil, bahwa tes gagal 2 kali berturut-turut. Tapi anda don't memiliki rutinitas yang secara otomatis menghapus sumber anda, jika unit-test gagal, apakah anda? Jalankan lagi!
Itu bisa gagal 3 kali berturut-turut? Mungkin anda harus mencoba keberuntungan di undian.
Kasus 2: Roll dadu
The dice roll pertanyaan adalah pertanyaan yang sama. Melempar dadu 6000 kali.
for (i in 0 to 6000)
++slot [Random.nextInt (6)];
return (slot.max - slot.min) < threshold;
Nah, anda'll pernah bisa 100% yakin, jadi yang terbaik yang dapat anda lakukan adalah bahwa hal itu's kemungkinan bahwa angka-angka yang acak. Memilih probabilitas -- mengatakan bahwa sampel angka atau barang-barang yang akan datang x kali diberikan juta sampel, dalam margin of error. Menjalankan hal satu juta kali, dan melihat apakah itu's dalam margin. Untungnya, komputer membuat hal semacam ini mudah untuk dilakukan.