Saya telah menghadapi masalah ini beberapa kali dalam beberapa tahun terakhir ketika menulis kode penanganan utas untuk beberapa proyek. Saya memberikan jawaban terlambat karena sebagian besar jawaban lainnya, sambil memberikan alternatif, sebenarnya tidak menjawab pertanyaan tentang pengujian. Jawaban saya ditujukan kepada kasus-kasus di mana tidak ada alternatif untuk kode multithreaded; Saya membahas masalah desain kode untuk kelengkapan, tetapi juga membahas pengujian unit.
Menulis kode multithread yang dapat diuji
Hal pertama yang harus dilakukan adalah memisahkan kode penanganan utas produksi Anda dari semua kode yang melakukan pemrosesan data aktual. Dengan begitu, pemrosesan data dapat diuji sebagai kode ulir tunggal, dan satu-satunya yang dilakukan kode multithread adalah mengoordinasikan utas.
Hal kedua yang perlu diingat adalah bahwa bug dalam kode multithread adalah probabilistik; bug yang paling sering memanifestasikan dirinya adalah bug yang akan menyelinap masuk ke dalam produksi, akan sulit untuk mereproduksi bahkan dalam produksi, dan dengan demikian akan menyebabkan masalah terbesar. Untuk alasan ini, pendekatan pengkodean standar penulisan kode dengan cepat dan kemudian debugging sampai berfungsi adalah ide yang buruk untuk kode multithreaded; itu akan menghasilkan kode di mana bug mudah diperbaiki dan bug berbahaya masih ada.
Sebaliknya, ketika menulis kode multithread, Anda harus menulis kode dengan sikap bahwa Anda akan menghindari penulisan bug di tempat pertama. Jika Anda telah menghapus kode pemrosesan data dengan benar, kode penanganan ulir harus cukup kecil - lebih disukai beberapa baris, paling buruk beberapa lusin baris - sehingga Anda memiliki kesempatan untuk menulisnya tanpa menulis bug, dan tentunya tanpa menulis banyak bug , jika Anda memahami threading, luangkan waktu Anda, dan berhati-hatilah.
Unit tes menulis untuk kode multithreaded
Setelah kode multithreaded ditulis selengkap mungkin, masih ada baiknya menulis tes untuk kode tersebut. Tujuan utama dari tes ini bukan untuk menguji bug kondisi ras yang sangat tergantung waktu - tidak mungkin untuk menguji kondisi ras seperti itu berulang - tetapi untuk menguji bahwa strategi penguncian Anda untuk mencegah bug seperti itu memungkinkan beberapa thread untuk berinteraksi sebagaimana dimaksud .
Untuk menguji perilaku penguncian yang benar dengan benar, tes harus memulai beberapa utas. Untuk membuat tes berulang, kami ingin interaksi antara utas terjadi dalam urutan yang dapat diprediksi. Kami tidak ingin menyinkronkan utas secara eksternal dalam pengujian, karena itu akan menutupi bug yang dapat terjadi dalam produksi di mana utas tidak disinkronkan secara eksternal. Itu meninggalkan penggunaan penundaan waktu untuk sinkronisasi utas, yang merupakan teknik yang telah saya gunakan dengan sukses setiap kali saya harus menulis tes kode multithread.
Jika penundaan terlalu pendek, maka pengujian menjadi rapuh, karena perbedaan waktu kecil - katakanlah antara mesin yang berbeda di mana tes dapat dijalankan - dapat menyebabkan waktu dimatikan dan tes gagal. Apa yang biasanya saya lakukan adalah mulai dengan penundaan yang menyebabkan kegagalan pengujian, tingkatkan penundaan sehingga pengujian dapat diandalkan pada mesin pengembangan saya, dan kemudian gandakan penundaan di luar itu sehingga pengujian memiliki peluang bagus untuk melewati mesin lain. Ini berarti bahwa pengujian akan memakan waktu makroskopis, meskipun menurut pengalaman saya, desain pengujian yang cermat dapat membatasi waktu itu tidak lebih dari selusin detik. Karena Anda seharusnya tidak memiliki banyak tempat yang membutuhkan kode koordinasi utas dalam aplikasi Anda, itu seharusnya dapat diterima untuk test suite Anda.
Akhirnya, catat jumlah bug yang ditangkap oleh pengujian Anda. Jika pengujian Anda memiliki cakupan kode 80%, maka diharapkan dapat menangkap sekitar 80% bug Anda. Jika pengujian Anda dirancang dengan baik tetapi tidak menemukan bug, ada kemungkinan Anda tidak memiliki bug tambahan yang hanya akan muncul dalam produksi. Jika tes menangkap satu atau dua bug, Anda mungkin masih beruntung. Di luar itu, dan Anda mungkin ingin mempertimbangkan peninjauan yang cermat atau bahkan penulisan ulang lengkap kode penanganan utas Anda, karena kemungkinan kode tersebut masih mengandung bug tersembunyi yang akan sangat sulit ditemukan hingga kode tersebut diproduksi, dan sangat sulit untuk diperbaiki.