Seharusnya tes unit hanya mencakup perangkat lunak 'fungsional'

9

Kami menggunakan StructureMap dalam proyek pengembangan perangkat lunak baru. Salah satu anggota tim telah menerapkan uji unit yang pada dasarnya menguji konfigurasi kontainer StructureMap . Ini melakukan ini dengan melakukan hal berikut;

  • Menghitung jumlah instance rakitan yang dikonfigurasikan untuk kelas di namespace aplikasi kami.
  • Menentukan instance yang diharapkan di tingkat kelas
  • Menyatakan bahwa instance yang diharapkan cocok dengan total instance yang ditemukan.
  • Menyatakan bahwa instance yang diharapkan cocok dengan yang didefinisikan dalam tes

Contohnya adalah;

var repositories = container.GetAllInstances<IEnvironmentRepository>();
Assert.AreEqual(1, repositories .Count());
foundInstances = foundInstances + repositories .Count();

Kami juga memiliki 'unit test' untuk kelas berikut;

public MyClass(IEnvironmentRepository environmentRepository)
        {

        }

Dalam tes ini, kami mengejek IEnvironmentRepository, jadi tidak akan menyuntikkannya dari wadah seperti yang akan terjadi pada sistem live.

Seorang kolega mengabaikan tes unit pada konfigurasi structuremap dengan komentar di sepanjang baris "Tes unit hanya menguji konfigurasi sendiri". Ini jelas tujuan dari tes dan menurut saya sangat valid. Saya bertanya kepada orang yang mengabaikan tes untuk menghapus konfigurasi structuremap untuk IEnvironmentRepository(dengan tes masih diabaikan) dan menjalankan unit test unit lengkap, mereka semua lulus. Kami kemudian menjalankan aplikasi dan gagal karena konfigurasi kontainer sekarang tidak valid. Menurut pendapat saya, ini membuktikan nilai tes, kolega saya masih tidak setuju. Dia hanya menyatakan bahwa kita tidak boleh menguji konfigurasi, tetapi saya anggap ini baik dalam pengiriman unit test.

Jadi sejumlah pertanyaan;

  • Apakah ini tes unit yang valid - Kami sedang menguji konfigurasi kontainer kami, bukan berarti structuremap berfungsi (tapi saya bisa melihat tumpang tindih)
  • Jika tidak, bagaimana Anda bisa memvalidasi konfigurasi tanpa mengujinya. Bagaimana Anda bisa menghentikan seseorang secara tidak sengaja menghapus baris kode yang diperlukan dan memeriksanya?
  • Haruskah MyClassunit test menyelesaikan instance dari IEnvironmentRepositorywadah dan meneruskannya?
ChrisBint
sumber
10
9 dari 10 ketidaksepakatan pada tes timbul dari kenyataan bahwa kerangka mendukung tes otomatis dalam segala bentuknya, dan orang-orang ingin masuk ke semantik apakah tes otomatis tertentu adalah baik dan benar unit test atau tidak. Tes yang Anda gambarkan terdengar seperti jenis-tidak-cukup-unit-tes-tes yang mungkin sangat berguna untuk memiliki dan mengotomatisasi (dan berjalan di checkin) - jangan menyebutnya unit test. Tanyakan apakah kolega Anda akan tidur lebih nyenyak di malam hari jika tes tinggal di fitur / folder sendiri yang jelas dipisahkan
Jeroen Mostert
2
Itu pendapat saya juga, mungkin berguna, dan meskipun tidak sepenuhnya merupakan unit test, itu menambah nilai dan ini telah terbukti. Tanggapannya adalah bahwa tes unit lain akan mengambil ini, tetapi menurut saya, jika mereka ditulis sebagai tes unit yang ketat, Anda akan diejek dependensi dan karena itu tidak akan pernah tahu apakah konfigurasi itu valid sampai Anda menggunakannya.
ChrisBint
4
Rekan Anda ada benarnya ketika dia mengatakan untuk tidak menguji konfigurasi, karena konfigurasi asli yang sebenarnya bisa bervariasi per penyebaran tidak dapat / tidak boleh diuji - siapa yang mengatakan "merah" salah dan "biru" tidak? Tes akan digabungkan secara ketat ke satu pengaturan. Tetapi konfigurasi yang terkait dengan artefak kode sedikit pengecualian, karena tidak bervariasi dan jelas ada cara untuk membuatnya salah. Idealnya, Anda memiliki konfigurasi seperti itu yang dihasilkan saat membangun dari metadata KERING, tetapi jika ini tidak layak, tes seperti ini menambah nilai. Lebih baik daripada kesalahan penerapan yang bisa dihindari.
Jeroen Mostert
2
Apa yang Anda gambarkan tidak menguji unit, tetapi menguji konfigurasi perangkat lunak pihak ketiga. Sangatlah bermanfaat untuk memiliki tes yang menguji hal-hal ini, tetapi itu adalah tes integrasi, bukan tes unit, dan pemutusan mungkin ada akar dari ketidaksepakatan.
Phoshi
3
@ ChrisBint Ya ampun, tidak, saya telah menulis banyak tes kontainer sendiri. Mereka memiliki banyak nilai, mereka hanya bukan unit test. Tidak apa-apa, tes integrasi sangat berharga untuk mengetahui hal-hal yang tidak dapat dilakukan pengujian unit .
Phoshi

Jawaban:

13

Ini adalah tes otomatis yang sangat valid untuk dimiliki. Saya menyebutnya "tes arsitektur" karena mereka memverifikasi tingkat kesehatan komponen kerangka basis kode Anda.

Apakah wadah IoC dapat menyelesaikan dan menyusun semua pohon objek dalam aplikasi? Bisakah Mapper otomatis memetakan antara semua objek yang terdaftar tanpa gagal? Apakah layer pusat dalam Arsitektur Bawang tidak mereferensikan sesuatu yang eksternal?

Tes-tes ini dapat menghemat banyak waktu Anda ketika bug konfigurasi masuk, dengan menunjuk pada penyebab yang tepat. Kerangka kerja yang baik akan memberi Anda pesan kesalahan yang sangat tepat tentang apa yang salah dan Anda mendapatkannya segera setelah Anda menjalankan tes (idealnya, terus menerus) alih-alih terkubur jauh di dalam jejak tumpukan runtime jika Anda beruntung.

Apakah mereka adalah unit test ... mungkin tidak, tetapi mereka masih beroperasi dalam memori untuk sebagian besar dan berjalan cukup cepat. Kemudian lagi, saya tidak tahu, tidak seperti ada definisi unit test yang diterima secara universal.

guillaume31
sumber
Ironisnya, ini cukup banyak bagaimana saya menjelaskannya kepada kolega saya dan bahkan dengan validasi (menghapus salah satu instance kontainer dan menjalankan aplikasi) ia masih tidak melihat nilai apa pun. Saya mengerti setiap orang memiliki pendapat mereka sendiri, dan saya menyuarakan pendapat saya;) Saya suka istilah "tes arsitektur", saya akan mencuri itu!
ChrisBint
6

Masalah dengan tes seperti ini yang menguji internal program, bukan persyaratan itu. Apakah tes itu dapat gagal bahkan jika program bekerja sesuai kebutuhan.

Dalam kasus Anda, setiap kali Anda mengubah pengaturan wadah, mungkin Anda memiliki ketergantungan baru yang perlu disuntikkan, Anda memecahkan tes Anda.

Selain itu, jika Anda menambahkan persyaratan ketergantungan ekstra, tetapi lupa untuk menambahkannya ke wadah dan ubah tes wadah. semuanya akan berlalu, tetapi program Anda akan macet.

Tes otomatis yang lebih baik akan memulai program dan melihat apakah itu crash.

Anda harus mengetahui jenis-jenis kesalahan ini saat integrasi atau pengujian UI meskipun mereka gagal dalam pengujian unit.

Karena itu, meningkatnya kompleksitas pengaturan wadah adalah rasa sakit di pantat. Mungkin beberapa tes 'buruk' tidak sia-sia.

Ewan
sumber
1

Tes unit tes kode. Apa pun di luar ini adalah pengujian otomatis "lainnya" - sebut saja apa yang Anda inginkan. Anda tampaknya menguji konfigurasi di sini. Jika konfigurasi dapat berubah tergantung pada lingkungan, itu tidak termasuk dalam unit test. Pertimbangkan untuk menambahkan atribut tes untuk menunjukkan bahwa tes ini memiliki tipe yang berbeda dengan tes lainnya.

Robbie Dee
sumber
Konfigurasi bersifat statis, tidak didorong oleh lingkungan, semua kelas yang ada dalam konfigurasi akan digunakan pada semua lingkungan dengan cara yang sama. Ya, jumlah instance yang bisa di konfigurasi harus sesuai dengan jumlah instance dalam konfigurasi, yang merupakan bagian dari tes. Seperti contoh saya menunjukkan, menghapus IEnvironmentRepository memungkinkan tes unit lain untuk lulus. Tes wadah khusus akan gagal pada 2 Asserts; 1 - Jumlah total deklarasi instance yang mungkin tidak cocok, dan 2 - jumlah instans spesifik dari IEnvironmentRepository tidak akan cocok.
ChrisBint
1
Kebenaran wadah didefinisikan oleh pembuat kode. Fakta bahwa kedua kode yang sedang diuji dan pengujian itu sendiri harus berubah untuk setiap modifikasi segera membuat bel alarm berbunyi. DI adalah sarana untuk mencapai tujuan dan bukan tujuan itu sendiri. Sangat mungkin untuk menulis kode dalam gaya DI tanpa strukturur ergo itu bukan tes unit bonafide dalam pandangan saya. Wadah tentu saja perlu dibuktikan tetapi kemanjuran melakukannya dengan tes otomatis tampaknya agak diperdebatkan dengan informasi terbatas yang disediakan di sini.
Robbie Dee
2
Tes unit membutuhkan 10 menit untuk mengetuk. Penempatan bisa memakan waktu lebih dari satu jam.
ChrisBint
1
Mengingat bagian dari unit test memvalidasi secara khusus keberadaan satu baris dalam konfigurasi, tidak yakin bagaimana itu tidak dapat lebih terisolasi. Hitungan umum yang bisa saya setujui.
ChrisBint
1
Mungkin ada jarak tempuh di dalamnya - panggilan penilaian untuk Anda benar-benar. Tetapi mereka harus dipisahkan baik secara fisik atau melalui beberapa atribut.
Robbie Dee
0

Tanggung jawab wadah injeksi ketergantungan adalah merekatkan berbagai modul dalam satu aplikasi yang berfungsi .

Jika Anda menulis tes otomatis untuk aplikasi Anda - Anda harus memiliki beberapa tes "integrasi (atau penerimaan) yang menjalankan tes" dari ujung ke ujung ", yang akan menguji seluruh pipa aplikasi Anda, bahwa semua modul yang terlibat dalam kasus uji tertentu direkatkan bersama dengan benar .

Jadi tes integrasi tersebut akan gagal jika wadah injeksi ketergantungan tidak dikonfigurasi dengan benar. Yang membuat pengujian unit untuk wadah itu sendiri tidak berguna, karena tes integrasi harus menunjukkan kemungkinan kesalahan dalam konfigurasi wadah.

Anda tidak perlu membahas semua kasus uji yang mungkin dalam tes integrasi, cukup satu kasus uji per fitur yang mencakup sepenuhnya dari UI ke database.

Jika kasus uji integrasi tidak mencakup contoh ketergantungan tertentu - Anda cukup menambahkan yang seperti itu.

Dengan tes integrasi, Anda dapat dengan bebas mengganti wadah tanpa menulis ulang unit test untuk konfigurasinya.

Fabio
sumber
0

IMO, jawabannya adalah:

  1. Apakah ini tes unit yang valid - Kami sedang menguji konfigurasi kontainer kami, bukan berarti structuremap berfungsi (tapi saya bisa melihat tumpang tindih)

    • Ini unit test yang valid untuk structuremap , bukan untuk proyek Anda, karena tes unitary menguji beberapa kode tertentu, mengejek semua dependensi jika perlu untuk menguji logika yang diterapkan. Logika konfigurasi diterapkan di dalam structuremap, oleh karena itu pustaka ini harus diuji dengan baik dan harus berisi unit test seperti yang Anda sebutkan, dan lebih banyak lagi: itu harus berisi ratusan tes seperti ini, secara dinamis mengejek beberapa konfigurasi saat runtime dan menguji untuk melihat apakah wadah berperilaku sebagaimana mestinya.
  2. Jika tidak, bagaimana Anda bisa memvalidasi konfigurasi tanpa mengujinya. Bagaimana Anda bisa menghentikan seseorang secara tidak sengaja menghapus baris kode yang diperlukan dan memeriksanya?

    • Anda dapat menguji konfigurasi secara manual di lingkungan yang diperlukan, dan Anda juga dapat membuat otomatisasi untuk ini (tes otomatis), yang menguji konfigurasi spesifik yang Anda butuhkan (tidak perlu mengejek hal-hal saat runtime).
  3. Haruskah uji unit MyClass menyelesaikan instance IEnvironmentRepository dari wadah dan meneruskannya?

    • Tidak, ini adalah unit test yang sempurna, karena Anda mengejek ketergantungan dan menguji logika MyClass secara terpisah.
Emerson Cardoso
sumber
-1

UnitTest memverifikasi perilaku unit yang diinginkan dalam pemisahan .

Ini berarti setiap jenis konfigurasi adalah tidak dalam lingkup UnitTests .

Meskipun demikian Anda harus memiliki tes otomatis untuk konfigurasi Anda, tetapi ini bukan UnitTests ...

Timothy Truckle
sumber
Di mana Anda mendapatkan definisi Unit?
ChrisBint
Saya suka salah satu dari Roy Osherove di The Art Of Unittesting : A Unit adalah setiap potongan kode (produksi-) yang memiliki alasan yang sama untuk berubah. Saya duniaku ini biasanya berkisar dari satu kelas hingga tiga atau lima ...
Timothy Truckle
Ini adalah kode produksi yang sedang diuji.
ChrisBint
Hanya ingin mengalihkan perhatian para nitpicker , tidak berharap itu bekerja sebaliknya juga ...; o)
Timothy Truckle