Menguji daftar ... Semua dalam tes yang sama atau satu tes untuk setiap kondisi?

21

Saya menguji bahwa suatu fungsi melakukan apa yang diharapkan pada daftar. Jadi saya ingin menguji

f(null) -> null
f(empty) -> empty
f(list with one element) -> list with one element
f(list with 2+ elements) -> list with the same number of elements, doing what expected

Untuk melakukannya, Apa pendekatan terbaik?

  • Menguji semua kasus dalam pengujian (metode) yang sama, dengan nama "WorksAsExpected"
  • Menempatkan satu tes untuk setiap kasus, sehingga memiliki
    • "Bekerja Seperti Yang DiharapkanKetikaNull"
    • "Bekerja Seperti Yang Diharapkan Saat Kekosongan"
    • "Bekerja Seperti Yang DiharapkanKetika Seling Tunggal"
    • "Bekerja Seperti Yang DiharapkanKetika Lebih BanyakLagi"
  • Pilihan lain yang tidak saya pikirkan :-)
malarres
sumber
2
Kemungkinan rangkap dari Apakah metode penulisan Tes Unit ini benar?
nyamuk
2
Saya akan menuliskannya sebagai test case yang terpisah. Anda dapat menggunakan tes berparameter jika sistem pengujian Anda mendukungnya.
jonrsharpe
5
Jika Anda menulis tes dalam status Diberikan ... Kapan ... Lalu, maka jelaslah bahwa tes itu harus diuji secara terpisah ...
Robbie Dee
1
Saya hanya ingin menambahkan: IMO, ada baiknya untuk memisahkan kasus tepi (seperti nol dan kosong) menjadi tes terpisah, karena ini sering melibatkan logika kasus khusus di berbagai implementasi yang mungkin, dan jika tes ini gagal, mereka akan menunjukkan dengan jelas dalam apa cara kode yang diuji gagal (Anda tidak perlu menggali lebih dalam, atau men-debug kasus uji untuk mencari tahu apa yang terjadi).
Filip Milovanović
1
Daftar dengan elemen duplikat?
atayenel

Jawaban:

30

Aturan praktis sederhana yang saya gunakan untuk apakah akan melakukan serangkaian tes dalam satu kasus uji, atau banyak, adalah: apakah hanya melibatkan satu pengaturan?

Jadi jika saya menguji bahwa, untuk beberapa elemen, keduanya memproses semuanya dan mendapatkan hasil yang benar, saya mungkin memiliki dua atau lebih konfirmasi, tetapi saya hanya perlu mengatur daftar sekali. Jadi satu test case baik-baik saja.

Dalam kasus Anda, saya harus mengatur daftar nol, daftar kosong dll. Itu banyak pengaturan. Jadi saya pasti akan membuat beberapa tes dalam kasus ini.

Seperti yang disebutkan orang lain, "beberapa pengujian" tersebut mungkin dapat eksis sebagai kasus uji parameter tunggal; yaitu uji kasus yang sama dijalankan terhadap berbagai data pengaturan. Kunci untuk mengetahui apakah ini solusi yang layak terletak pada bagian lain dari tes ini: "aksi" dan "tegaskan". Jika Anda dapat melakukan tindakan yang sama dan menegaskan pada setiap kumpulan data, maka gunakan pendekatan ini. Jika Anda menambahkan diri ifmisalnya menjalankan kode yang berbeda terhadap bagian data yang berbeda, maka ini bukan solusinya. Gunakan kasus uji individual dalam kasus terakhir.

David Arno
sumber
14

Ada kompromi. Semakin banyak Anda mengemas dalam satu tes, semakin besar kemungkinan Anda akan memiliki efek bawang mencoba untuk membuatnya lulus. Dengan kata lain, kegagalan pertama menghentikan tes itu. Anda tidak akan tahu tentang pernyataan lain sampai Anda memperbaiki kegagalan pertama. Yang mengatakan, memiliki banyak unit test yang sebagian besar mirip kecuali untuk kode pengaturan adalah banyak pekerjaan yang sibuk hanya untuk mengetahui bahwa beberapa pekerjaan seperti yang ditulis dan yang lainnya tidak.

Alat yang mungkin, berdasarkan kerangka kerja Anda:

  • Teori . Sebuah teori memungkinkan Anda menguji serangkaian fakta tentang sekumpulan data. Kerangka kerja kemudian akan memberi makan pengujian Anda dengan beberapa skenario data pengujian - baik dengan bidang atau dengan metode statis yang menghasilkan data. Jika beberapa fakta Anda berlaku berdasarkan beberapa prasyarat dan yang lain tidak, kerangka kerja ini memperkenalkan konsep asumsi . Anda Assume.that()cukup melewatkan tes untuk data jika gagal prasyarat. Ini memungkinkan Anda mendefinisikan "Bekerja seperti yang diharapkan" dan kemudian cukup memberinya banyak data. Saat Anda melihat hasilnya, Anda memiliki entri untuk tes induk dan kemudian sub-entri untuk setiap bagian data.
  • Tes Parameter . Tes parameter adalah pendahulu teori, jadi mungkin tidak ada yang memeriksa prasyarat yang dapat Anda miliki dengan teori. Hasil akhirnya adalah sama. Anda Anda melihat hasilnya, Anda memiliki entri orang tua untuk tes itu sendiri, dan kemudian entri khusus untuk setiap titik data.
  • Satu tes dengan beberapa penegasan . Dibutuhkan lebih sedikit waktu untuk melakukan pengaturan, tetapi Anda akhirnya menemukan masalah sedikit demi sedikit. Jika tes terlalu lama dan ada banyak skenario berbeda yang diuji, ada dua risiko besar: akan butuh waktu lama untuk berjalan, dan tim Anda akan muak dengannya dan mematikan tes.
  • Beberapa tes dengan implementasi serupa . Penting untuk dicatat bahwa jika asersinya berbeda, tes mereka tidak tumpang tindih. Namun, ini akan menjadi kebijaksanaan konvensional dari tim fokus TDD.

Saya bukan dari pola pikir yang ketat bahwa hanya akan ada satu assertpernyataan dalam pengujian Anda, tetapi saya menempatkan batasan bahwa semua pernyataan harus menguji post-kondisi satu tindakan. Jika satu-satunya perbedaan antara tes adalah data, saya dari pola pikir untuk menggunakan fitur tes data didorong lebih lanjut seperti tes parameter atau teori.

Timbang pilihan Anda untuk memutuskan apa hasil terbaik. Saya akan mengatakan bahwa "WorksAsExpectedWhenNull" pada dasarnya berbeda dari setiap kasus di mana Anda berurusan dengan koleksi yang memiliki berbagai elemen.

Berin Loritsch
sumber
5

Itu adalah kasus uji yang berbeda, tetapi kode untuk tes ini sama. Oleh karena itu, menggunakan uji parameterisasi merupakan solusi terbaik. Jika kerangka kerja pengujian Anda tidak mendukung parameterisasi, ekstrak kode bersama menjadi fungsi pembantu, dan panggil dari setiap kasus uji.

Cobalah untuk menghindari parametrization melalui loop dalam satu test case, karena itu membuat sulit untuk menentukan set data mana yang menyebabkan kesalahan.

Dalam siklus merah-hijau-refactor TDD Anda, Anda harus menambahkan satu contoh data yang ditetapkan pada suatu waktu. Menggabungkan beberapa uji kasus menjadi uji parametrized akan menjadi bagian dari langkah refactoring.

Pendekatan yang agak berbeda adalah pengujian properti . Anda akan membuat berbagai tes (parametrized) yang menegaskan berbagai properti fungsi Anda, tanpa menentukan data input konkret. Misalnya properti dapat: untuk semua daftar xs, daftar ys = f(xs)memiliki panjang yang sama dengan xs. Kerangka pengujian kemudian akan menghasilkan daftar menarik dan daftar acak, dan menyatakan bahwa properti Anda berlaku untuk semuanya. Ini menjauh dari menentukan contoh secara manual, karena memilih contoh secara manual dapat melewatkan kasus tepi yang menarik.

amon
sumber
Bukankah "miss" dalam kalimat terakhir adalah "find"?
Robbie Dee
@RobbieDee Bahasa Inggris bersifat ambigu, tetap.
amon
3

Memiliki satu tes untuk setiap kasus sesuai karena menguji konsep tunggal dalam setiap tes adalah pedoman yang baik yang sering direkomendasikan.

Lihat posting ini: Apakah boleh memiliki beberapa pernyataan dalam pengujian unit tunggal? . Ada diskusi yang relevan dan terperinci di sana:

Pedoman saya biasanya bahwa Anda menguji satu KONSEP logis per tes. Anda dapat memiliki beberapa penegasan tentang objek yang sama. mereka biasanya akan menjadi konsep yang sama sedang diuji. Sumber - Roy Osherove

[...]

Tes harus gagal hanya karena satu alasan, tetapi itu tidak selalu berarti bahwa seharusnya hanya ada satu pernyataan yang tegas. IMHO, lebih penting memegang pola "Atur, Tindak, Tegas".

Kuncinya adalah bahwa Anda hanya memiliki satu tindakan, dan kemudian Anda memeriksa hasil dari tindakan itu menggunakan pernyataan. Tapi itu adalah "Atur, Bertindak, Tegas, Akhir dari ujian". Jika Anda tergoda untuk melanjutkan pengujian dengan melakukan tindakan lain dan lebih banyak konfirmasi sesudahnya, lakukan itu sebagai tes terpisah. Sumber

nak
sumber
0

Menurut saya, itu tergantung pada kondisi tes.

  • Jika tes Anda hanya memiliki 1 kondisi untuk mengatur tes, tetapi banyak efek samping. multi-assert dapat diterima.
  • Tetapi ketika Anda memiliki beberapa kondisi, berarti Anda memiliki beberapa test case, masing-masing harus dicakup oleh 1 unit test saja.
HungDL
sumber
ini berbunyi lebih seperti komentar, lihat Bagaimana Menjawab
nyamuk