Apa cara terbaik untuk mengatur pengujian unit kami

18

Kami telah membangun sejumlah besar unit test untuk program utama kami selama ini. Beberapa ribu. Masalahnya adalah kita tidak memiliki gagasan yang jelas tentang tes apa yang kita miliki karena ada begitu banyak. Dan itu masalah karena kita tidak tahu di mana kita lemah dalam tes (atau di mana kita memiliki duplikat).

Aplikasi kami adalah mesin pelaporan. Jadi Anda dapat memiliki templat yang digunakan untuk menguji penguraian (apakah kami membaca semua properti tabel), menggabungkan data (apakah kami menyimpan properti tabel yang benar dalam penggabungan), memformat halaman akhir (adalah tabel yang ditempatkan dengan benar pada halaman) ), dan / atau format output (adalah file DOCX yang dibuat benar).

Tambahkan ke ini apa yang perlu kita uji. Ambil bantalan di sekitar sel tabel (kami menggunakan Word, Excel, & PowerPoint untuk desain laporan). Kita harus menguji padding pada page break, untuk tabel di dalam sel, sel yang digabung secara vertikal, sel yang digabungkan secara horizontal, sel yang digabungkan secara vertikal & horizontal yang berisi tabel dengan sel yang digabungkan secara vertikal & horizontal di tabel bagian dalam, di mana tabel itu menerobos satu halaman.

Jadi kategori apa yang masuk dalam tes itu? Padding tabel, page break, sel bersarang, sel yang digabungkan secara vertikal, sel yang digabungkan secara horizontal, atau yang lainnya?

Dan bagaimana kita mendokumentasikan kategori-kategori ini, menamai unit test, dll.?

Pembaruan: Sejumlah orang menyarankan menggunakan alat cakupan untuk memverifikasi bahwa kami memiliki cakupan penuh. Sayangnya itu penggunaan terbatas dalam kasus kami karena bug cenderung disebabkan oleh kombinasi spesifik sehingga kode yang semuanya telah diuji, tetapi tidak dalam kombinasi itu.

Sebagai contoh, kami memiliki pelanggan kemarin yang memulai bookmark Word di akhir loop forEach dalam template mereka (dokumen Word) dan mengakhirinya di awal forEach loop berikutnya. Ini semua menggunakan kode yang memiliki unit test yang menentangnya, tetapi kami belum memikirkan kombinasi templat yang memperluas awal bookmark yang akan dimulai 25 kali, lalu berakhir 10 kali (dua forEach loop memiliki jumlah baris yang berbeda).

David Thielen
sumber
1
Sepertinya pertanyaan Anda benar-benar, Bagaimana kami tahu kami telah menguji skenario tertentu?
Andy Wiesendanger
Iya! Dan juga di mana tes untuk skenario serupa. Dan dari situ kita mendapatkan kebutuhan # 2 - membaca apa yang dibahas membantu kita menemukan apa yang kita lewatkan.
David Thielen

Jawaban:

13

Secara umum, saya cenderung mirror pohon sumber untuk tes unit saya. Jadi, jika saya memiliki src / lib / fubar, saya akan memiliki tes / lib / fubar yang akan berisi tes unit untuk fubar.

Namun, apa yang Anda uraikan adalah tes yang lebih fungsional. Dalam hal ini, saya akan memiliki tabel multi-dimensi yang menyebutkan semua kondisi Anda yang mungkin. Kemudian, yang tidak memiliki tes tidak masuk akal atau perlu tes baru. Anda bisa, tentu saja, kemudian meletakkannya di set suite tes.

Sardathrion - Pasang kembali Monica
sumber
Kami saat ini mencerminkan pohon sumber. Tapi kami punya dua masalah. Pertama, untuk pemformatan tabel, ada lebih dari 100 tes yang berbeda. Melacak apa yang sebenarnya diuji telah menjadi masalah. Kedua, area fungsional yang sangat berbeda perlu untuk menguji tabel - parser, substitusi data, pemformatan, dan pembuatan dokumen keluaran. Jadi saya pikir Anda benar, dalam arti itu adalah pengujian fungsional properti yang diberikan.
David Thielen
Yang mengarah ke pertanyaan, di mana kita menyimpan tabel tes? Saya sedang memikirkan spreadsheet di direktori sumber root ???
David Thielen
Saya akan menyimpannya dalam spreadsheet versi terkontrol di direktori tes. Jika Anda memiliki banyak hal yang perlu Anda uji, memecahnya menjadi struktur meta akan bermanfaat. Coba pikirkan dalam hal apa hal umum sedang diuji alih-alih apa atau bagaimana.
Sardathrion
7

Struktur yang paling umum tampaknya adalah srcdantest cermin direktori.

src/module/class
test/module/class_test

Namun, ada struktur alternatif yang saya lihat yang sekarang saya yakini lebih baik.

src/module/class
src/module/class_test

Karena unit test cenderung mencerminkan kelas yang mereka uji, menempatkannya di direktori yang sama memberikan akses yang jauh lebih mudah ke file sehingga Anda dapat bekerja di kedua sisi secara berdampingan.

ming_codes
sumber
2
Salah satu kelemahan dari pendekatan sebelumnya adalah bahwa setiap kali Anda memutuskan untuk mengubah struktur file proyek, Anda harus melakukan hal yang sama untuk struktur tes. Masalah ini tidak ada jika tes di mana kode berada.
victor175
5

Dalam .NET, saya cenderung untuk mencerminkan, atau setidaknya perkiraan, struktur namespace untuk kode sumber dalam proyek uji, di bawah "Tests.Unit" atau "Tests.Integration" master namespace. Semua pengujian unit dilakukan dalam satu proyek, dengan struktur dasar kode sumber direplikasi sebagai folder dalam proyek. Sama untuk tes integrasi. Jadi, solusi sederhana untuk proyek mungkin terlihat seperti ini:

Solution
   MyProduct.Project1 (Project)
      Folder1 (Folder)
         ClassAA (Class def)
         ...
      Folder2
         ClassAB
         ...
      ClassAC
      ...
   MyProduct.Project2
      Folder1
         ClassBA
         ...
      ClassBB
      ...
   ...
   MyProduct.Tests.Unit
      Project1
         Folder1
            ClassAATests
            ClassAATests2 (possibly a different fixture setup)
         Folder2
            ClassABTests
         ClassACTests
      Project2
         Folder1
            ClassBATests
         ClassBBTests
      ...
   MyProduct.Tests.Integration
      Project1 (a folder named similarly to the project)
         Folder1 (replicate the folders/namespaces for that project beneath)
            ClassAATests
         Folder2
            ClassABTests
         ClassACTests
      Project2
         Folder1
            ClassBATests
         ClassBBTests

Untuk AAT atau AEET yang dikodekan dengan kerangka kerja pengujian unit, ini sedikit berubah; biasanya tes tersebut mencerminkan serangkaian langkah, yang akan menguji fungsionalitas use case atau cerita baru. Saya biasanya menyusun tes-tes ini dalam sebuah MyProduct.Tests.Acceptanceproyek, dengan tes untuk setiap cerita, mungkin dikelompokkan berdasarkan tonggak sejarah atau kisah "epik" yang menjadi bagian dari cerita yang sedang dikembangkan. Namun, itu benar-benar hanya tes integrasi uber, dan jadi jika Anda lebih suka menyusun tes dalam cara yang lebih berorientasi objek daripada gaya cerita Anda bahkan tidak memerlukan MyProduct.Tests.Acceptanceproyek atau serupa; cukup lemparkan mereka di MyProduct.Tests.Integrationbawah cakupan objek level tertinggi yang diuji.

KeithS
sumber
3

Tidak ada alasan untuk uji unit hanya dalam satu kategori. Semua perangkat uji unit utama mendukung pembuatan suite uji , yang menggabungkan tes untuk kategori tertentu. Ketika area kode tertentu telah diubah, pengembang harus menjalankan suite itu terlebih dahulu dan sering melihat apa yang rusak. Ketika sebuah tes menyangkut padding dan istirahat dan bersarang, tentu saja memasukkannya ke dalam tiga suite.

Yang mengatakan, titik unit test adalah menjalankannya sepanjang waktu, yaitu mereka harus kecil dan cukup cepat sehingga layak untuk menjalankannya semuanya sebelum melakukan kode apa pun. Dengan kata lain, tidak masalah apa pun kategori tes, itu harus dijalankan sebelum melakukan apa pun. Suites benar-benar hanya sebuah penopang yang Anda gunakan jika karena alasan tertentu Anda tidak dapat menulis tes secepat yang seharusnya.

Adapun cakupan, ada alat cakupan yang sangat baik yang memberi tahu Anda berapa persen garis sebenarnya dilakukan dengan menjalankan tes Anda - ini adalah petunjuk yang jelas untuk tes apa yang masih Anda lewatkan.

Sedangkan untuk penamaan, tidak ada nilai khusus dalam upaya pengeluaran pada nama - nama unit test. Semua yang ingin Anda dengar dari tes Anda adalah "5235 dari 5235 tes lulus". Ketika sebuah tes gagal, apa yang Anda baca bukan namanya, tetapi pesannya , misalnya String di dalam assert()yang mengimplementasikan kriteria kesuksesan Anda. Pesan tersebut harus cukup informatif sehingga Anda memiliki gagasan tentang apa yang salah tanpa membaca isi ujian. Nama itu tidak penting dibandingkan dengan itu.

Kilian Foth
sumber
Setuju 100% untuk semua yang Anda katakan (mesin build kami menjalankan semua tes pada saat check-in). Masalah besar kami adalah melacak apa yang kami uji. Dan cakupan kode tidak banyak membantu (lihat pembaruan di atas).
David Thielen
1

Salah satu cara untuk mengetahui apakah Anda lemah dalam tes adalah keterlacakan. Biasanya untuk tes, ini berbentuk liputan.

Tujuannya adalah untuk mengukur bagian kode mana yang digunakan oleh tes Anda, sehingga Anda dapat melihat kode yang tidak tercakup oleh tes Anda. Terserah Anda (dan alat cakupan) untuk menentukan apa "bagian dari kode" itu. Paling tidak adalah jangkauan cabang.

mouviciel
sumber