it-swarm-id.com

Apakah pengujian atau unit test lebih penting?

Baik assert dan unit test berfungsi sebagai dokumentasi untuk basis kode, dan sarana untuk menemukan bug. Perbedaan utama adalah bahwa fungsi menegaskan sebagai kewarasan memeriksa dan melihat input nyata, sedangkan tes unit berjalan pada input simulasi spesifik dan merupakan tes terhadap "jawaban benar" tunggal yang jelas. Apa manfaat relatif dari menggunakan tes vs unit test sebagai alat utama memverifikasi kebenaran? Menurut Anda, mana yang harus lebih ditekankan?

52
dsimcha

Asserts berguna untuk memberi tahu Anda tentang status internal program. Misalnya, bahwa struktur data Anda memiliki status yang valid, mis., Bahwa struktur data Time tidak akan menyimpan nilai 25:61:61. Kondisi yang diperiksa dengan menegaskan adalah:

  • Prasyarat, yang memastikan bahwa penelepon menjaga kontraknya,

  • Postconditions, yang memastikan bahwa callee menyimpan kontraknya, dan

  • Invarian, yang memastikan bahwa struktur data selalu memiliki beberapa properti setelah fungsi kembali. Invarian adalah suatu kondisi yang merupakan prasyarat dan postkondisi.

Tes unit berguna untuk memberi tahu Anda tentang perilaku eksternal modul. Stack Anda mungkin memiliki status konsisten setelah metode Push() dipanggil, tetapi jika ukuran tumpukan tidak bertambah tiga setelah disebut tiga kali, maka itu adalah kesalahan . (Misalnya, kasus sepele di mana implementasi Push() yang salah hanya memeriksa pernyataan dan keluar.)

Sebenarnya, perbedaan utama antara tes menegaskan dan unit adalah bahwa tes unit memiliki data uji (nilai untuk menjalankan program), sedangkan menegaskan tidak. Artinya, Anda dapat menjalankan tes unit Anda secara otomatis, sementara Anda tidak dapat mengatakan hal yang sama untuk pernyataan. Demi diskusi ini, saya berasumsi bahwa Anda berbicara tentang mengeksekusi program dalam konteks tes fungsi tingkat tinggi (yang menjalankan seluruh program, dan tidak menggerakkan modul seperti tes unit). Jika Anda tidak berbicara tentang tes fungsi otomatis sebagai sarana untuk "melihat input nyata", maka jelas nilainya terletak pada otomatisasi, dan dengan demikian unit test akan menang. Jika Anda membicarakan hal ini dalam konteks pengujian fungsi (otomatis), lihat di bawah.

Mungkin ada beberapa tumpang tindih dalam apa yang sedang diuji. Sebagai contoh, postcondition Stack sebenarnya dapat menyatakan bahwa ukuran stack bertambah satu. Tetapi ada batasan untuk apa yang dapat dilakukan dalam pernyataan itu: Haruskah itu juga memeriksa bahwa elemen atas adalah apa yang baru saja ditambahkan?

Untuk keduanya, tujuannya adalah untuk meningkatkan kualitas. Untuk pengujian unit, tujuannya adalah untuk menemukan bug. Untuk pernyataan, tujuannya adalah untuk mempermudah debugging dengan mengamati status program yang tidak valid segera setelah terjadi.

Perhatikan bahwa tidak satupun teknik memverifikasi kebenaran. Bahkan, jika Anda melakukan pengujian unit dengan tujuan untuk memverifikasi program itu benar, Anda kemungkinan akan datang dengan tes yang tidak menarik yang Anda tahu akan berhasil. Ini efek psikologis: Anda akan melakukan apa pun untuk memenuhi tujuan Anda. Jika tujuan Anda adalah menemukan bug, aktivitas Anda akan mencerminkan hal itu.

Keduanya penting, dan memiliki tujuan masing-masing.

[Sebagai catatan terakhir tentang pernyataan: Untuk mendapatkan nilai maksimal, Anda harus menggunakannya di semua titik kritis dalam program Anda, dan bukan beberapa fungsi utama. Jika tidak, sumber asli masalah mungkin telah ditutup dan sulit dideteksi tanpa berjam-jam melakukan debugging.]

43
Macneil

Saat berbicara tentang asersi, perlu diingat bahwa asersi dapat dimatikan dengan cepat.

Contoh pernyataan yang sangat buruk:

char *c = malloc(1024);
assert(c != NULL);

Kenapa ini buruk? Karena tidak ada pemeriksaan kesalahan yang dilakukan jika pernyataan dilewati karena sesuatu seperti NDEBUG didefinisikan.

Tes unit akan (kemungkinan) hanya memisahkan pada kode di atas. Tentu, itu melakukan tugasnya dengan memberi tahu Anda bahwa ada yang salah, atau bukan? Seberapa besar kemungkinan malloc() gagal dalam pengujian?

Pernyataan adalah untuk tujuan debugging ketika seorang programmer perlu menyiratkan bahwa tidak ada kejadian 'normal' yang akan menyebabkan pernyataan tersebut untuk menyala. malloc() gagal adalah, memang peristiwa normal, oleh karena itu tidak boleh ditegaskan.

Ada banyak kasus lain di mana pernyataan digunakan alih-alih secara memadai menangani hal-hal yang mungkin salah. Inilah sebabnya mengapa pernyataan mendapatkan reputasi buruk, dan mengapa bahasa seperti Go tidak memasukkannya.

Tes unit dirancang untuk memberi tahu Anda ketika sesuatu yang Anda ubah merusak sesuatu yang lain. Mereka dirancang untuk menyelamatkan Anda (dalam kebanyakan kasus) dari melalui setiap fitur program (namun, penguji adalah penting untuk rilis) setiap kali Anda membuat sebuah bangunan.

Sebenarnya tidak ada korelasi yang jelas antara keduanya, selain keduanya memberitahu Anda bahwa ada sesuatu yang salah. Pikirkan penegasan sebagai breakpoint dalam sesuatu yang sedang Anda kerjakan, tanpa harus menggunakan debugger. Pikirkan unit test sebagai sesuatu yang memberitahu Anda jika Anda memecahkan sesuatu yang Anda tidak sedang bekerja.

7
Tim Post

Keduanya adalah alat yang digunakan untuk membantu meningkatkan kualitas keseluruhan sistem yang Anda bangun. Banyak tergantung pada bahasa yang Anda gunakan, jenis aplikasi yang Anda buat, dan di mana waktu Anda dihabiskan. Belum lagi Anda memiliki beberapa aliran pemikiran tentang hal itu.

Untuk memulainya, jika Anda menggunakan bahasa tanpa kata kunci assert, Anda tidak dapat menggunakan keterangan (setidaknya tidak dengan cara kita berbicara di sini). Untuk waktu yang lama, Java tidak memiliki kata kunci assert, dan sejumlah bahasa masih tidak. Pengujian unit kemudian menjadi sedikit lebih penting. Dalam beberapa bahasa pernyataan hanya dijalankan ketika flag diatur (lagi dengan Java di sini). Ketika proteksi tidak selalu ada, itu bukan fitur yang sangat berguna.

Ada aliran pemikiran yang mengatakan jika Anda "menegaskan" sesuatu, Anda mungkin juga menulis if/throw blok pengecualian yang bermakna. Proses pemikiran ini berasal dari banyak penegasan yang ditempatkan di awal metode untuk memastikan semua nilai terikat. Menguji prasyarat Anda adalah bagian yang sangat penting untuk mendapatkan kondisi pascakemudian yang diharapkan.

Pengujian unit adalah kode tambahan yang harus ditulis dan dipelihara. Bagi banyak orang ini adalah kelemahan. Namun, dengan pemotongan kerangka kerja unit test saat ini di luar sana, Anda dapat menghasilkan sejumlah besar kondisi pengujian dengan kode yang relatif sedikit. Tes parameter dan "teori" akan melakukan tes yang sama dengan sejumlah besar sampel data yang dapat mengungkap beberapa bug yang sulit ditemukan.

Saya pribadi menemukan saya mendapatkan lebih banyak jarak tempuh dengan pengujian unit daripada menaburkan menegaskan, tapi itu karena platform yang saya kembangkan pada sebagian besar waktu (Java/C #). Bahasa lain memiliki dukungan pernyataan yang lebih kuat, dan bahkan "Desain dengan Kontrak" (lihat di bawah) untuk memberikan lebih banyak jaminan. Jika saya bekerja dengan salah satu bahasa ini, saya mungkin menggunakan DBC lebih dari pengujian unit.

http://en.wikipedia.org/wiki/Design_by_contract#Languages_with_native_support

5
Berin Loritsch