Enum adalah tipe terbatas, dengan nama khusus (semoga bermakna). Enum mungkin hanya memiliki satu nilai, seperti void
yang hanya berisi null
(beberapa bahasa menyebutnya unit
, dan menggunakan nama void
untuk enum tanpa elemen!). Ini mungkin memiliki dua nilai, seperti bool
yang memiliki false
dan true
. Mungkin ada tiga, seperti colourChannel
dengan red
, green
dan blue
. Dan seterusnya.
Jika dua enum memiliki jumlah nilai yang sama, maka keduanya "isomorfik"; yaitu jika kita mengganti semua nama secara sistematis maka kita dapat menggunakan satu di tempat yang lain dan program kita tidak akan berperilaku berbeda. Secara khusus, tes kami tidak akan berlaku berbeda!
Misalnya, result
mengandung win
/ lose
/ draw
isomorfis di atas colourChannel
, karena kita dapat mengganti mis colourChannel
dengan result
, red
dengan win
, green
dengan lose
dan blue
dengan draw
, dan selama kita melakukannya di mana-mana (produsen dan konsumen, parser dan serialisers, entri basis data, file log, dll. ) maka tidak akan ada perubahan dalam program kami. " colourChannel
Tes" apa pun yang kami tulis masih akan berlalu, meskipun tidak colourChannel
ada lagi!
Juga, jika suatu enum mengandung lebih dari satu nilai, kita selalu dapat mengatur ulang nilai-nilai itu untuk mendapatkan enum baru dengan jumlah nilai yang sama. Karena jumlah nilai tidak berubah, pengaturan baru isomorfik dengan yang lama, dan karenanya kami bisa mengganti semua nama dan tes kami masih akan berlalu (perhatikan bahwa kami tidak bisa begitu saja mengubah definisi; kami harus masih alihkan semua situs yang digunakan juga).
Artinya, sejauh menyangkut mesin, enum adalah "nama yang dapat dibedakan" dan tidak ada yang lain . Satu-satunya hal yang dapat kita lakukan dengan enum adalah bercabang pada apakah dua nilai itu sama (misalnya red
/ red
) atau berbeda (misalnya red
/ blue
). Jadi itulah satu-satunya hal yang dapat dilakukan 'unit test', misalnya
( red == red ) || throw TestFailure;
(green == green) || throw TestFailure;
( blue == blue ) || throw TestFailure;
( red != green) || throw TestFailure;
( red != blue ) || throw TestFailure;
...
Seperti yang dikatakan @ jesm00, tes semacam itu memeriksa implementasi bahasa alih-alih program Anda. Tes-tes ini tidak pernah merupakan ide yang baik: bahkan jika Anda tidak mempercayai implementasi bahasa, Anda harus mengujinya dari luar , karena itu tidak dapat dipercaya untuk menjalankan tes dengan benar!
Jadi itulah teorinya; bagaimana dengan praktiknya? Masalah utama dengan karakterisasi enum ini adalah bahwa program 'dunia nyata' jarang mandiri: kami memiliki versi lawas, penyebaran jarak jauh / tertanam, data historis, cadangan, basis data langsung, dll. Sehingga kami tidak pernah bisa benar-benar 'beralih' semua kemunculan nama tanpa kehilangan kegunaan.
Namun hal-hal semacam itu bukanlah 'tanggung jawab' enum itu sendiri: mengubah enum mungkin memutuskan komunikasi dengan sistem jarak jauh, tetapi sebaliknya kita mungkin memperbaiki masalah seperti itu dengan mengubah enum!
Dalam skenario tersebut, enum adalah merah-herring: bagaimana jika satu sistem perlu untuk menjadi ini cara, dan lain perlu untuk menjadi yang cara? Tidak mungkin keduanya, tidak peduli berapa banyak tes yang kami tulis! Penyebab sesungguhnya di sini adalah antarmuka input / output, yang seharusnya menghasilkan / menggunakan format yang didefinisikan dengan baik alih-alih "integer apa pun yang mengambil interpretasi". Jadi solusi sebenarnya adalah menguji antarmuka i / o : dengan unit test untuk memeriksa apakah ia menguraikan / mencetak format yang diharapkan, dan dengan tes integrasi untuk memeriksa apakah format tersebut benar-benar diterima oleh pihak lain.
Kita mungkin masih bertanya-tanya apakah enum sedang 'dilaksanakan dengan cukup menyeluruh', tetapi dalam hal ini enum lagi-lagi merupakan ikan haring merah. Yang sebenarnya kami pedulikan adalah test suite itu sendiri . Kami dapat memperoleh kepercayaan di sini dalam beberapa cara:
- Cakupan kode dapat memberi tahu kami jika variasi nilai enum yang berasal dari rangkaian uji cukup untuk memicu berbagai cabang dalam kode. Jika tidak, kita dapat menambahkan tes yang memicu cabang yang tidak tertutup, atau menghasilkan variasi enum yang lebih luas dalam pengujian yang ada.
- Pemeriksaan properti dapat memberi tahu kami jika berbagai cabang dalam kode sudah cukup untuk menangani kemungkinan runtime. Misalnya, jika kode hanya menangani
red
, dan kami hanya menguji red
, maka kami memiliki cakupan 100%. Pemeriksa properti akan (mencoba) menghasilkan contoh tandingan untuk pernyataan kami, seperti menghasilkan green
dan blue
nilai yang kami lupa uji.
- Pengujian mutasi dapat memberi tahu kita apakah pernyataan kita benar-benar memeriksa enum, daripada hanya mengikuti cabang dan mengabaikan perbedaannya.