Saya cukup pemula dalam pengujian kode, dan pernah menjadi assert
pelacur sebelumnya. Satu hal yang mengkhawatirkan saya dalam unit testing adalah bahwa sering kali mengharuskan Anda untuk membuat public
(atau setidaknya internal
) bidang yang private
seharusnya, untuk melepaskan readonly
mereka, membuat private
metode protected virtual
sebagai gantinya, dll ...
Baru-baru ini saya menemukan bahwa Anda dapat menghindari ini dengan menggunakan hal-hal seperti kelas PrivateObject untuk mengakses apa pun dalam objek melalui refleksi. Tapi ini membuat tes Anda kurang dapat dipertahankan (hal-hal akan gagal pada eksekusi daripada waktu kompilasi, itu akan rusak oleh perubahan nama sederhana, lebih sulit untuk debug ...). Apa pendapat Anda tentang ini? Apa praktik terbaik dalam pengujian unit terkait pembatasan akses?
sunting: pertimbangkan misalnya bahwa Anda memiliki kelas dengan cache di file pada disk, dan dalam tes Anda, Anda ingin menulis ke memori sebagai gantinya.
sumber
Jawaban:
Anda seharusnya tidak pernah harus melakukannya
Terutama un-readonlying bidang dapat membuat objek abadi berubah, dan itu akan menjadi bencana.
Pengujian Anda harus mempertimbangkan objek Anda sebagai kotak hitam ( Wikipedia ), yang berarti bahwa mereka hanya harus peduli dengan antarmuka publik dari objek, bukan dengan detail implementasi mereka.
Jika suatu objek tidak dapat diuji secara memadai menggunakan antarmuka publiknya, maka Anda perlu menemukan cara untuk memberikan ekstensi formal dan berguna untuk antarmuka yang akan memfasilitasi pengujian. Sebagai contoh, sistem pendaftaran dengan hanya sepasang metode Daftar / Deregister mungkin akan mendapat manfaat dari metode IsRegistered bahkan jika itu tidak diperlukan untuk aplikasi yang ada; tetap, ini adalah ekstensi formal dan berguna untuk antarmuka, dan itu akan, secara kebetulan, mengakomodasi pengujian.
Yang penting adalah bahwa mengubah implementasi objek seharusnya tidak mengharuskan Anda untuk mengubah unit test. Secara teori Anda harus dapat menulis unit test satu kali, dan kemudian meminta beberapa programmer untuk mengkode beberapa implementasi yang sama sekali berbeda dari objek yang akan diuji untuk bekerja dengan unit test.
sumber
private
metodeprotected virtual
untuk membantu mengejek dalam tes dianggap praktik buruk?Di C # Anda dapat menggunakan
InternalsVisibleToAttribute
untuk memungkinkan rakitan pengujian Anda melihatinternal
kelas dalam rakitan yang Anda uji. Sepertinya Anda sudah tahu ini.Dalam kebanyakan kasus, saya hanya tertarik untuk menguji API publik dari perakitan saya. Dalam kasus di mana saya ingin melakukan pengujian kotak putih pada beberapa unit, saya memindahkan kode ke
internal
kelas, dan menjadikannyapublic
metode kelas itu. Lalu saya bisa kode tes unit untuk kelas itu.Ini cocok untuk injeksi ketergantungan dan pola strategi. Anda bisa mengabstraksi metode menjadi antarmuka, menyuntikkan antarmuka ke konstruktor objek induk Anda, dan hanya menguji apakah delegasi induk tepat. Kemudian Anda dapat menguji bahwa objek anak berperilaku tepat. Ini membuat semuanya lebih modular.
sumber
Dalam pengalaman saya, yang terbaik adalah tidak mengekspos internal kelas Anda khusus untuk ujian. Meskipun ini mungkin tampak untuk membuat tes lebih mudah untuk ditulis. Tes ini adalah klien pertama kelas Anda, jadi jika sulit untuk menguji kelas Anda melalui antarmuka publiknya, mungkin akan sulit untuk menggunakan kelas Anda di tempat lain juga.
Seberapa mudah kelas untuk menguji melalui API publik adalah umpan balik tentang betapa mudahnya kelas akan digunakan. Pikirkan tes sebagian sebagai cara untuk membuat prototipe penggunaan kelas Anda.
Coba pertimbangkan mengapa tes Anda perlu merasakan sesuatu tentang kelas yang tidak tersedia melalui API publik. Mungkin kelas Anda melakukan terlalu banyak dan perlu diuraikan menjadi sekelompok kelas yang bekerja sama? Kemudian Anda dapat mengejek beberapa kelas yang berkolaborasi untuk merasakan apa yang sedang dilakukan kelas.
Cobalah untuk menerapkan prinsip inversi dependensi dan memperkenalkan antarmuka antara kelas Anda yang dapat Anda tiru dalam tes Anda. Anda dapat menyediakan kolaborator untuk pengujian Anda dengan menggunakan inversi kontrol .
Juga pertimbangkan untuk menerapkan prinsip "kirim jangan tanya" untuk membantu menyusun antarmuka kelas Anda dengan cara yang kuat, longgar, di mana informasi yang tepat terbuka dan sisanya disembunyikan.
sumber
Secara pribadi saya lebih suka meninggalkan kode yang saya uji semurni mungkin dan jika kode pengujian perlu diretas (dan dalam C ++ pointer jahat dll) Saya senang melakukan itu.
sumber
Visibilitas kode Anda tidak ada hubungannya dengan tes unit Anda!
Anda menjadikan metode Anda pribadi bukan dengan tujuan untuk menyembunyikannya dari pengujian dan Anda tidak membuatnya terbuka untuk diekspos untuk pengujian, bukan? Ini adalah implementasi Anda yang penting di sini, bukan tes - server itu sebagai bukti kode Anda, tetapi itu bukan kode Anda .
Ada banyak cara untuk memungkinkan akses ke metode dan properti tersembunyi (pribadi atau internal). Banyak kerangka kerja pengujian dan IDE (misalnya, Visual Studio) mendukung Anda di sini dengan menghasilkan semua yang diperlukan untuk akses, Anda hanya perlu menulis kasus pengujian Anda. Jadi, mengapa khawatir? Lebih baik menjaga kode Anda tetap bersih dan rapi.
sumber