Proyek saya saat ini, secara ringkas, melibatkan penciptaan "kejadian acak yang terbatas". Saya pada dasarnya membuat jadwal inspeksi. Beberapa dari mereka didasarkan pada batasan jadwal yang ketat; Anda melakukan inspeksi sekali seminggu pada hari Jumat pukul 10:00 pagi. Inspeksi lain adalah "acak"; ada persyaratan dasar yang dapat dikonfigurasi seperti "inspeksi harus dilakukan 3 kali per minggu", "inspeksi harus terjadi antara jam 9 pagi - 9 malam", dan "tidak boleh ada dua inspeksi dalam periode 8 jam yang sama", tetapi dalam batasan apa pun yang dikonfigurasikan untuk serangkaian inspeksi tertentu, tanggal dan waktu yang dihasilkan tidak dapat diprediksi.
Tes unit dan TDD, IMO, memiliki nilai besar dalam sistem ini karena dapat digunakan untuk membangunnya secara bertahap sementara persyaratan lengkapnya masih belum lengkap, dan pastikan saya tidak "melakukan rekayasa berlebihan" untuk melakukan hal-hal yang saya tidak lakukan. saat ini tahu saya perlu. Jadwal yang ketat adalah sepotong kue untuk TDD. Namun, saya merasa sulit untuk benar-benar mendefinisikan apa yang saya uji ketika saya menulis tes untuk bagian acak dari sistem. Saya dapat menyatakan bahwa semua waktu yang dihasilkan oleh penjadwal harus berada dalam batasan, tetapi saya bisa menerapkan algoritma yang melewati semua tes tersebut tanpa waktu yang sebenarnya sangat "acak". Sebenarnya itulah yang terjadi; Saya menemukan masalah di mana waktu, meskipun tidak dapat diprediksi dengan tepat, jatuh ke bagian kecil dari rentang tanggal / waktu yang diijinkan. Algoritma masih melewati semua pernyataan yang saya rasa bisa saya buat secara masuk akal, dan saya tidak bisa merancang tes otomatis yang akan gagal dalam situasi itu, tetapi lulus ketika diberi hasil "lebih acak". Saya harus menunjukkan masalah diselesaikan dengan merestrukturisasi beberapa tes yang ada untuk mengulangi diri mereka beberapa kali, dan secara visual memeriksa bahwa waktu yang dihasilkan berada dalam kisaran penuh yang diijinkan.
Adakah yang punya tips untuk merancang tes yang seharusnya mengharapkan perilaku non-deterministik?
Terima kasih untuk semua sarannya. Pendapat utama tampaknya adalah bahwa saya memerlukan tes deterministik untuk mendapatkan hasil yang deterministik, berulang, tegas . Masuk akal.
Saya membuat satu set tes "kotak pasir" yang berisi kandidat algoritma untuk proses pembatas (proses dimana array byte yang bisa panjang menjadi panjang antara min dan max). Saya kemudian menjalankan kode itu melalui loop FOR yang memberikan algoritma beberapa byte array yang dikenal (nilai dari 1 hingga 10.000.000 hanya untuk memulai) dan memiliki algoritma membatasi masing-masing ke nilai antara 1009 dan 7919 (Saya menggunakan bilangan prima untuk memastikan Algoritma tidak akan melewati beberapa GCF kebetulan antara rentang input dan output). Nilai-nilai terbatas yang dihasilkan dihitung dan histogram dihasilkan. Untuk "lulus", semua input harus tercermin dalam histogram (kewarasan untuk memastikan kami tidak "kehilangan" apa pun), dan perbedaan antara dua ember dalam histogram tidak boleh lebih besar dari 2 (harus benar-benar <= 1 , tapi tetap disini). Algoritma pemenang, jika ada, dapat dipotong dan disisipkan langsung ke dalam kode produksi dan tes permanen dilakukan untuk regresi.
Ini kodenya:
private void TestConstraintAlgorithm(int min, int max, Func<byte[], long, long, long> constraintAlgorithm)
{
var histogram = new int[max-min+1];
for (int i = 1; i <= 10000000; i++)
{
//This is the stand-in for the PRNG; produces a known byte array
var buffer = BitConverter.GetBytes((long)i);
long result = constraintAlgorithm(buffer, min, max);
histogram[result - min]++;
}
var minCount = -1;
var maxCount = -1;
var total = 0;
for (int i = 0; i < histogram.Length; i++)
{
Console.WriteLine("{0}: {1}".FormatWith(i + min, histogram[i]));
if (minCount == -1 || minCount > histogram[i])
minCount = histogram[i];
if (maxCount == -1 || maxCount < histogram[i])
maxCount = histogram[i];
total += histogram[i];
}
Assert.AreEqual(10000000, total);
Assert.LessOrEqual(maxCount - minCount, 2);
}
[Test, Explicit("sandbox, does not test production code")]
public void TestRandomizerDistributionMSBRejection()
{
TestConstraintAlgorithm(1009, 7919, ConstrainByMSBRejection);
}
private long ConstrainByMSBRejection(byte[] buffer, long min, long max)
{
//Strip the sign bit (if any) off the most significant byte, before converting to long
buffer[buffer.Length-1] &= 0x7f;
var orig = BitConverter.ToInt64(buffer, 0);
var result = orig;
//Apply a bitmask to the value, removing the MSB on each loop until it falls in the range.
var mask = long.MaxValue;
while (result > max - min)
{
mask >>= 1;
result &= mask;
}
result += min;
return result;
}
[Test, Explicit("sandbox, does not test production code")]
public void TestRandomizerDistributionLSBRejection()
{
TestConstraintAlgorithm(1009, 7919, ConstrainByLSBRejection);
}
private long ConstrainByLSBRejection(byte[] buffer, long min, long max)
{
//Strip the sign bit (if any) off the most significant byte, before converting to long
buffer[buffer.Length - 1] &= 0x7f;
var orig = BitConverter.ToInt64(buffer, 0);
var result = orig;
//Bit-shift the number 1 place to the right until it falls within the range
while (result > max - min)
result >>= 1;
result += min;
return result;
}
[Test, Explicit("sandbox, does not test production code")]
public void TestRandomizerDistributionModulus()
{
TestConstraintAlgorithm(1009, 7919, ConstrainByModulo);
}
private long ConstrainByModulo(byte[] buffer, long min, long max)
{
buffer[buffer.Length - 1] &= 0x7f;
var result = BitConverter.ToInt64(buffer, 0);
//Modulo divide the value by the range to produce a value that falls within it.
result %= max - min + 1;
result += min;
return result;
}
... dan inilah hasilnya:
Penolakan LSB (menggeser-geser angkanya sampai masuk dalam kisaran) adalah TERRIBLE, untuk alasan yang sangat mudah untuk dijelaskan; ketika Anda membagi angka dengan 2 sampai kurang dari maksimum, Anda berhenti segera setelah itu, dan untuk rentang non-sepele, yang akan membiaskan hasil menuju sepertiga atas (seperti yang terlihat dalam hasil rinci histogram ). Ini persis perilaku yang saya lihat dari tanggal selesai; semua waktu di sore hari, pada hari-hari yang sangat spesifik.
Penolakan MSB (menghapus bit paling signifikan dari nomor satu pada satu waktu sampai berada dalam kisaran) lebih baik, tetapi sekali lagi, karena Anda memotong angka yang sangat besar dengan setiap bit, itu tidak terdistribusi secara merata; Anda tidak mungkin mendapatkan angka di ujung atas dan bawah, sehingga Anda bias ke sepertiga tengah. Itu mungkin menguntungkan seseorang yang ingin "menormalkan" data acak menjadi kurva lonceng, tetapi jumlah dua atau lebih angka acak yang lebih kecil (mirip dengan melempar dadu) akan memberi Anda kurva yang lebih alami. Demi tujuan saya, itu gagal.
Satu-satunya yang lulus tes ini adalah dibatasi oleh divisi modulo, yang juga ternyata yang tercepat dari ketiganya. Modulo akan, menurut definisinya, menghasilkan distribusi sebanyak mungkin dengan input yang tersedia.
sumber
Jawaban:
Apa yang sebenarnya ingin Anda uji di sini, saya asumsikan, adalah karena diberikan serangkaian hasil spesifik dari pengacak, sisa metode Anda berkinerja dengan benar.
Jika itu yang Anda cari maka tirulah pengacak, untuk membuatnya deterministik dalam bidang pengujian.
Saya biasanya memiliki objek tiruan untuk semua jenis data yang tidak dapat ditentukan atau tidak dapat diprediksi (pada saat penulisan tes), termasuk generator GUID dan DateTime. Sekarang.
Edit, dari komentar: Anda harus mengejek PRNG (istilah itu lolos dari saya tadi malam) pada tingkat serendah mungkin - yaitu. ketika itu menghasilkan array byte, bukan setelah Anda mengubahnya menjadi Int64s. Atau bahkan pada kedua level, sehingga Anda dapat menguji konversi Anda ke array Int64 berfungsi sebagaimana dimaksud dan kemudian menguji secara terpisah bahwa konversi Anda ke array DateTimes berfungsi sebagaimana dimaksud. Seperti yang dikatakan Jonathon, Anda bisa melakukannya dengan memberikan set seed, atau Anda dapat memberikan array byte untuk dikembalikan.
Saya lebih suka yang terakhir karena tidak akan rusak jika implementasi kerangka kerja PRNG berubah. Namun, satu keuntungan untuk memberikannya benih adalah bahwa jika Anda menemukan sebuah kasus dalam produksi yang tidak berfungsi sebagaimana dimaksud, Anda hanya perlu mencatat satu nomor untuk dapat menggandakannya, sebagai lawan dari keseluruhan susunan.
Semua ini mengatakan, Anda harus ingat bahwa itu disebut Pseudo Random Number Generator karena suatu alasan. Mungkin ada beberapa bias bahkan pada level itu.
sumber
Ini akan terdengar seperti jawaban bodoh, tapi saya akan membuangnya di sana karena ini adalah bagaimana saya melihatnya dilakukan sebelumnya:
Pisahkan kode Anda dari PRNG - berikan benih pengacakan ke semua kode yang menggunakan pengacakan. Kemudian Anda dapat menentukan nilai 'bekerja' dari satu biji (atau beberapa biji yang akan membuat Anda merasa lebih baik). Ini akan memberi Anda kemampuan untuk menguji kode Anda secara memadai tanpa harus bergantung pada hukum jumlah besar.
Kedengarannya gila, tetapi beginilah cara militer melakukannya (entah itu atau mereka menggunakan 'tabel acak' yang sama sekali tidak acak)
sumber
"Apakah ini acak (cukup)" ternyata menjadi pertanyaan yang sangat halus. Jawaban singkatnya adalah bahwa tes unit tradisional tidak akan memotongnya - Anda harus menghasilkan banyak nilai acak dan mengirimkannya ke berbagai tes statistik yang memberi Anda kepercayaan tinggi bahwa mereka cukup acak untuk kebutuhan Anda.
Akan ada sebuah pola - kita menggunakan generator nomor psuedo-random. Tetapi pada titik tertentu hal-hal akan menjadi "cukup baik" untuk aplikasi Anda (di mana cukup banyak BANYAK bervariasi antara katakan game di satu ujung, di mana generator yang relatif sederhana sudah cukup, semua jalan sampai ke kriptografi di mana Anda benar-benar perlu urutan yang tidak layak untuk menentukan oleh penyerang yang gigih dan lengkap).
Artikel Wikipedia http://en.wikipedia.org/wiki/Randomness_tests dan tautan tindak lanjutnya memiliki informasi lebih lanjut.
sumber
Saya punya dua jawaban untuk Anda.
=== JAWABAN PERTAMA ===
Segera setelah saya melihat judul pertanyaan Anda, saya datang untuk melompat dan mengusulkan solusinya. Solusi saya sama dengan apa yang diusulkan beberapa orang lain: untuk mengejek generator nomor acak Anda. Lagi pula, saya telah membangun beberapa program berbeda yang memerlukan trik ini untuk menulis tes unit yang baik, dan saya mulai membuat akses yang dapat dipermainkan ke angka acak sebagai praktik standar dalam semua pengkodean saya.
Tapi kemudian saya membaca pertanyaan Anda. Dan untuk masalah khusus yang Anda gambarkan, itu bukan jawabannya. Masalah Anda bukan karena Anda perlu membuat proses yang dapat diprediksi menggunakan angka acak (jadi itu bisa diuji). Sebaliknya, masalah Anda adalah untuk memverifikasi bahwa algoritma Anda memetakan output acak seragam dari RNG Anda ke output uniform-dalam-kendala dari algoritma Anda - bahwa jika RNG yang mendasarinya seragam maka akan menghasilkan waktu inspeksi yang terdistribusi secara merata (tergantung pada kendala masalah).
Itu masalah yang sangat sulit (tapi cukup jelas). Yang berarti ini adalah masalah MENARIK. Saya segera mulai memikirkan beberapa ide hebat untuk menyelesaikannya. Kembali ketika saya adalah seorang programmer jagoan saya mungkin sudah mulai melakukan sesuatu dengan ide-ide ini. Tapi saya bukan programmer jagoan lagi ... Saya suka bahwa saya lebih berpengalaman dan lebih terampil sekarang.
Jadi alih-alih menyelam ke masalah yang sulit, saya berpikir dalam hati: apa nilai dari ini? Dan jawabannya mengecewakan. Bug Anda sudah dipecahkan, dan Anda akan rajin dengan masalah ini di masa depan. Keadaan eksternal tidak dapat memicu masalah, hanya perubahan pada algoritma Anda. Satu-satunya alasan untuk mengatasi masalah yang menarik ini adalah untuk memenuhi praktik TDD (Test Driven Design). Jika ada satu hal yang saya pelajari adalah bahwa dengan membabi buta mengikuti praktik apa pun saat tidak bernilai menyebabkan masalah. Saran saya adalah ini: Hanya saja jangan menulis tes untuk ini, dan lanjutkan.
=== JAWABAN KEDUA ===
Wow ... masalah yang sangat keren!
Yang perlu Anda lakukan di sini adalah menulis tes yang memverifikasi bahwa algoritma Anda untuk memilih tanggal dan waktu inspeksi akan menghasilkan output yang terdistribusi secara seragam (dalam kendala masalah) jika RNG yang digunakannya menghasilkan angka yang terdistribusi secara merata. Berikut adalah beberapa pendekatan, diurutkan berdasarkan tingkat kesulitan.
Anda dapat menerapkan brute force. Jalankan algoritma beberapa kali saja, dengan RNG nyata sebagai input. Periksa hasil keluaran untuk melihat apakah hasilnya terdistribusi secara merata. Tes Anda harus gagal jika distribusi bervariasi dari seragam sempurna dengan lebih dari ambang batas tertentu, dan untuk memastikan Anda menangkap masalah ambang batas tidak dapat disetel terlalu rendah. Itu berarti bahwa Anda akan memerlukan sejumlah besar menjalankan untuk memastikan bahwa probabilitas positif palsu (kegagalan uji secara acak) sangat kecil (baik <1% untuk basis kode berukuran sedang; bahkan lebih sedikit untuk basis kode besar).
Pertimbangkan algoritma Anda sebagai fungsi yang mengambil rangkaian semua output RNG sebagai input, lalu menghasilkan waktu inspeksi sebagai output. Jika Anda tahu bahwa fungsi ini terus menerus, maka ada cara untuk menguji properti Anda. Ganti RNG dengan RNG yang dapat diolok-olok dan jalankan algoritma beberapa kali, menghasilkan output RNG yang terdistribusi secara merata. Jadi, jika kode Anda membutuhkan 2 panggilan RNG, masing-masing dalam kisaran [0..1], Anda mungkin harus menjalankan algoritme sebanyak 100 kali, mengembalikan nilai [(0,0,0.0), (0,0,0.1), (0,0, 0.2), ... (0.0.0.9), (0.1.0.0), (0.1.0.1), ... (0.9.0.9)]. Kemudian Anda dapat memeriksa apakah output 100 berjalan (kurang-lebih) terdistribusi secara merata dalam rentang yang diizinkan.
Jika Anda BENAR-BENAR perlu memverifikasi algoritma dengan cara yang dapat diandalkan dan Anda tidak dapat membuat asumsi tentang algoritma ATAU menjalankan sejumlah besar kali, maka Anda masih dapat menyerang masalah, tetapi Anda mungkin perlu beberapa kendala tentang bagaimana Anda memprogram algoritma . Lihat PyPy dan pendekatan Object Space mereka sebagai contoh. Anda bisa membuat Object Space yang, bukannya benar-benar mengeksekusi algoritma, alih-alih hanya menghitung bentuk distribusi output (dengan asumsi bahwa input RNG seragam). Tentu saja, ini mengharuskan Anda membuat alat seperti itu dan algoritma Anda dibuat di PyPy atau alat lain di mana mudah untuk membuat modifikasi drastis ke kompiler dan menggunakannya untuk menganalisis kode.
sumber
Untuk pengujian unit, ganti generator acak dengan kelas yang menghasilkan hasil yang dapat diprediksi yang mencakup semua kasing sudut . Yaitu memastikan pseudo-randomizer Anda menghasilkan nilai serendah mungkin dan nilai setinggi mungkin, dan hasil yang sama beberapa kali berturut-turut.
Anda tidak ingin unit test Anda diabaikan misalnya bug off-by-one terjadi ketika Random.nextInt (1000) mengembalikan 0 atau 999.
sumber
Anda mungkin ingin melihat Sevcikova et al: "Pengujian Otomatis Sistem Stochastic: Suatu Pendekatan yang Dibumi Secara Statistik" ( PDF ).
Metodologi ini diimplementasikan dalam berbagai uji kasus untuk platform simulasi UrbanSim .
sumber
Pendekatan histogram sederhana adalah langkah pertama yang baik, tetapi tidak cukup untuk membuktikan keacakan. Untuk PRNG yang seragam Anda juga akan (paling tidak) menghasilkan sebar plot 2 dimensi (di mana x adalah nilai sebelumnya dan y adalah nilai baru). Plot ini juga harus seragam. Ini rumit dalam situasi Anda karena ada non-linearitas yang disengaja dalam sistem.
Pendekatan saya adalah:
Setiap tes ini bersifat statistik dan membutuhkan sejumlah besar titik sampel untuk menghindari positif palsu dan negatif palsu dengan tingkat kepercayaan yang tinggi.
Adapun sifat dari algoritma konversi / kendala:
Diberikan: metode untuk menghasilkan nilai pseudo-acak p di mana 0 <= p <= M
Need: output y dalam (mungkin diskontinu) kisaran 0 <= y <= N <= M
Algoritma:
r = floor(M / N)
, yaitu, jumlah rentang output lengkap yang sesuai dengan rentang input.p_max = r * N
p_max
ditemukany = p / r
Kuncinya adalah membuang nilai yang tidak dapat diterima daripada melipat secara tidak seragam.
dalam pseudo-code:
sumber
Selain memvalidasi bahwa kode Anda tidak gagal, atau melempar pengecualian tepat di tempat yang tepat, Anda dapat membuat pasangan input / respons yang valid (bahkan menghitung ini secara manual), masukkan input dalam tes dan pastikan itu mengembalikan respons yang diharapkan. Tidak hebat, tapi hanya itu yang bisa Anda lakukan, imho. Namun, dalam kasus Anda itu tidak benar-benar acak, setelah Anda membuat jadwal Anda, Anda dapat menguji kepatuhan aturan - harus memiliki 3 inspeksi per minggu, antara 9-9; tidak ada kebutuhan nyata atau kemampuan untuk menguji waktu yang tepat ketika inspeksi terjadi.
sumber
Benar-benar tidak ada cara yang lebih baik daripada menjalankannya beberapa kali dan melihat apakah Anda mendapatkan distribusi yang Anda inginkan. Jika Anda memiliki 50 jadwal inspeksi potensial yang diizinkan, Anda menjalankan tes 500 kali dan memastikan setiap jadwal digunakan hampir 10 kali. Anda dapat mengontrol benih generator acak Anda untuk membuatnya lebih deterministik, tetapi itu juga akan membuat pengujian Anda lebih erat dengan rincian implementasi.
sumber
Tidak mungkin menguji kondisi samar-samar yang tidak memiliki definisi konkret. Jika tanggal yang dihasilkan lulus semua tes maka secara teoritis aplikasi Anda berfungsi dengan benar. Komputer tidak dapat memberi tahu Anda jika tanggalnya "cukup acak" karena tidak dapat mengakui kriteria untuk pengujian semacam itu. Jika semua tes lulus tetapi perilaku aplikasi masih tidak cocok maka cakupan tes Anda tidak memadai secara empiris (dari perspektif TDD).
Dalam pandangan saya, yang terbaik adalah menerapkan beberapa batasan pembuatan tanggal yang sewenang-wenang sehingga distribusinya lulus tes bau manusia.
sumber
Catat saja output pengacak Anda (apakah pseudo atau kuantum / kacau atau dunia nyata). Kemudian simpan dan putar ulang urutan "acak" yang sesuai dengan persyaratan pengujian Anda, atau yang mengungkap potensi masalah dan bug, saat Anda membuat kotak uji unit Anda.
sumber
Kasus ini tampaknya ideal untuk Pengujian Berbasis Properti .
Singkatnya, ini adalah mode pengujian di mana kerangka kerja pengujian menghasilkan input untuk kode yang sedang diuji dan pernyataan pengujian memvalidasi properti dari output. Kerangka kerja kemudian bisa cukup pintar untuk "menyerang" kode yang sedang diuji dan mencoba memojokkannya menjadi kesalahan. Kerangka kerja ini biasanya juga cukup pintar untuk membajak seed generator nomor acak Anda. Biasanya Anda dapat mengkonfigurasi kerangka kerja untuk menghasilkan paling banyak N test case atau menjalankan paling banyak N detik, dan ingat test case yang gagal dari run terakhir dan jalankan kembali ini terhadap versi kode yang lebih baru terlebih dahulu. Hal ini memungkinkan untuk siklus iterasi cepat selama pengembangan dan pengujian komprehensif lambat dari band / in CI.
Inilah contoh (bodoh, gagal) yang menguji
sum
fungsi:sum
dipanggil dan properti hasil divalidasiTes ini akan menemukan banyak "bug" di
sum
(komentar jika Anda dapat menebak semua ini sendiri):sum([]) is 0
(int, bukan float)sum([-0.9])
negatifsum([0.0])
tidak sepenuhnya positifsum([..., nan]) is nan
yang tidak positifDengan pengaturan default,
hpythesis
batalkan tes setelah 1 input "buruk" ditemukan, yang bagus untuk TDD. Saya pikir itu mungkin untuk mengkonfigurasinya untuk melaporkan banyak / semua input "buruk", tetapi saya tidak dapat menemukan opsi itu sekarang.Dalam kasus OP, properti yang divalidasi akan lebih kompleks: inspeksi tipe A sekarang, inspeksi tipe A tiga kali seminggu, waktu inspeksi B selalu pada pukul 12 siang, inspeksi tipe C dari 9 hingga 9, [jadwal yang diberikan selama satu minggu] inspeksi jenis A, B, C semuanya ada, dll.
Perpustakaan yang paling terkenal adalah QuickCheck for Haskell, lihat halaman Wikipedia di bawah ini untuk daftar perpustakaan seperti itu dalam bahasa lain:
https://en.wikipedia.org/wiki/QuickCheck
Hipotesis (untuk Python) memiliki artikel yang bagus tentang pengujian semacam ini:
https://hypothesis.works/articles/what-is-property-based-testing/
sumber
yang dapat Anda uji unit adalah logika menentukan apakah tanggal acak valid atau jika tanggal acak lain perlu dipilih.
Tidak ada cara untuk menguji generator tanggal acak pendek mendapatkan banyak tanggal dan memutuskan apakah mereka sesuai acak.
sumber
Tujuan Anda bukan untuk menulis unit test dan lulus, tetapi untuk memastikan bahwa program Anda memenuhi persyaratannya. Satu-satunya cara Anda dapat melakukan ini, adalah dengan tepat mendefinisikan persyaratan Anda di tempat pertama. Misalnya, Anda menyebutkan "tiga inspeksi mingguan secara acak". Saya akan mengatakan persyaratannya adalah: (a) 3 inspeksi (bukan 2 atau 4), (b) pada waktu yang tidak dapat diprediksi oleh orang-orang yang tidak ingin diperiksa secara tak terduga, dan (c) tidak terlalu berdekatan - dua inspeksi yang terpisah lima menit mungkin tidak ada gunanya, mungkin juga tidak terlalu jauh.
Jadi, Anda menuliskan persyaratan lebih tepatnya daripada saya. (a) dan (c) mudah. Untuk (b), Anda dapat menulis beberapa kode sepintar mungkin yang mencoba memprediksi pemeriksaan selanjutnya, dan untuk lulus uji unit, kode itu tidak boleh dapat memprediksi lebih baik daripada perkiraan murni.
Dan tentu saja Anda perlu menyadari bahwa jika inspeksi Anda benar-benar acak, algoritma prediksi apa pun bisa benar secara kebetulan, jadi Anda harus yakin bahwa Anda dan unit test Anda tidak panik jika itu terjadi. Mungkin melakukan beberapa tes lagi. Saya tidak akan repot-repot menguji generator angka acak, karena pada akhirnya itu jadwal inspeksi yang diperhitungkan, dan tidak masalah bagaimana itu dibuat.
sumber