Bagaimana cara menguji tes?


53

Kami menguji kode kami untuk membuatnya lebih benar (sebenarnya, kecil kemungkinannya akan salah ). Namun, tes juga merupakan kode - mereka juga dapat mengandung kesalahan. Dan jika tes Anda buggy, mereka hampir tidak membuat kode Anda lebih baik.

Saya dapat memikirkan tiga jenis kemungkinan kesalahan dalam pengujian:

  1. Kesalahan logis, ketika programmer salah memahami tugas yang dihadapi, dan tes melakukan apa yang menurutnya harus dilakukan, yang mana salah;

  2. Kesalahan dalam kerangka pengujian yang mendasarinya (mis. Abstraksi mengejek yang bocor);

  3. Bug dalam tes: tes ini melakukan sedikit berbeda dari apa yang dipikirkan oleh programmer.

Ketik (1) kesalahan tampaknya tidak mungkin dicegah (kecuali programmer hanya ... menjadi lebih pintar). Namun, (2) dan (3) mungkin dapat ditelusuri. Bagaimana Anda menangani jenis kesalahan ini? Apakah Anda memiliki strategi khusus untuk menghindarinya? Misalnya, apakah Anda menulis beberapa tes "kosong" khusus, yang hanya memeriksa prasangka penulis uji? Juga, bagaimana Anda mendekati debugging kasus uji yang rusak?


3
Setiap bagian pengantar yang saya baca tentang mengejek sepertinya menimpa masalah ini. Setelah Anda mulai mengejek hal-hal tes selalu tampak lebih rumit daripada kode yang mereka uji. Jelas ini kurang mungkin terjadi ketika menguji kode dunia nyata, tetapi cukup mengecewakan ketika Anda mencoba untuk belajar.
Carson63000

@ Carson63000 Jika ini adalah tes sederhana yang menguji sesuatu dengan tiruan yang diuji , kompleksitasnya terbagi dan terkendali (, saya pikir).
mlvljr

13
Tapi lalu bagaimana Anda menguji tes tes?
ocodo

+1. Butir 1 bisa menjadi kesalahan persyaratan. Hanya dapat dicegah dengan meninjau persyaratan. Mungkin keluar dari tangan programmer kecuali jika mereka juga analis persyaratan
MarkJ

@ocodo: Cara yang sama Anda menonton Watchers. :)
Greg Burghardt

Jawaban:


18

Tes sudah diuji. Pengujian secara desain dilindungi dari bug, karena pengujian hanya mendeteksi perbedaan antara kode dan harapan kami. Jika ada masalah, kami memiliki kesalahan. Kesalahan bisa dalam kode atau dengan probabilitas yang sama dalam pengujian.

  1. Ada beberapa teknik yang mencegah Anda menambahkan bug yang sama di kedua kode dan tes Anda:

    1. Klien harus orang yang berbeda dari pelaksana.
    2. Pertama-tama tulis tes dan kemudian kode (seperti dalam Test Driven Development).
  2. Anda tidak perlu menguji platform yang mendasarinya. Tes tidak hanya menggunakan kode yang ditulis oleh Anda, tetapi juga menjalankan kode dari platform. Meskipun Anda tidak perlu ingin menangkap bug di platform pengujian, sangat sulit untuk menulis kode dan tes yang selalu menyembunyikan bug di platform, dengan kata lain sangat sulit untuk memiliki bug sistematis di kedua tes / kode dan di platform, dan probabilitas diturunkan dengan setiap tes yang Anda buat. Bahkan jika Anda akan mencoba melakukan ini, Anda akan memiliki tugas yang sangat sulit.

  3. Anda dapat memiliki bug dalam tes tetapi biasanya mereka ditangkap dengan mudah karena tes diuji oleh kode yang dikembangkan. Antara kode dan tes Anda memiliki umpan balik penegakan diri. Keduanya membuat prediksi tentang bagaimana panggilan spesifik antarmuka harus berperilaku. Jika responsnya berbeda Anda tidak perlu memiliki bug dalam kode. Anda dapat memiliki bug dalam tes juga.


Jawaban yang sangat bagus Saya suka ide loop yang memperkuat diri antara tes dan kode dan pengamatan bahwa akan sulit untuk menulis tes secara konsisten menyembunyikan bug di platform yang mendasarinya.
Ryszard Szopa

yang tidak mencegah tes dibuat berdasarkan asumsi yang salah tentang apa yang harus dilakukan kode sebenarnya. Yang dapat menyebabkan bug yang sangat jahat tetap tidak terdeteksi selama pengujian. Satu-satunya cara untuk mencegahnya adalah dengan membuat tes yang ditulis oleh pihak ketiga tanpa ada hubungan sama sekali dengan organisasi yang menulis kode yang sebenarnya, sehingga mereka tidak dapat "mencemari" pemikiran masing-masing ketika datang untuk menafsirkan dokumen persyaratan.
jwenting

24

Cobalah membuat tes individual sekecil mungkin.

Ini seharusnya mengurangi kemungkinan membuat bug. Bahkan jika Anda berhasil membuatnya, lebih mudah ditemukan. Tes unit seharusnya kecil dan spesifik, dengan toleransi rendah untuk kegagalan dan penyimpangan.

Pada akhirnya, itu mungkin hanya masalah pengalaman. Semakin banyak tes yang Anda tulis, semakin baik Anda melakukannya, semakin sedikit kesempatan Anda untuk melakukan tes jelek.


3
Bagaimana jika tes membutuhkan pengaturan yang agak rumit? Terkadang hal-hal semacam ini tidak berada di bawah kendali Anda.
Ryszard Szopa

Yah, saya kira pengaturan yang rumit adalah "kondisi awal" dari tes. Jika itu gagal, semua tes Anda harus gagal. Bahkan, saya sedang mengerjakan proyek seperti itu sekarang, dan orang-orang yang tidak pernah menggunakan unit test terus-menerus menanyakan hal yang sama..sampai kami menjelaskan unit test yang sebenarnya :) Kemudian mereka menyadari hal itu dapat dilakukan, meskipun luar biasa kompleksitas proyek.
dr Hannibal Lecter

Apa cara terbaik untuk memeriksa bahwa "kondisi awal" ini terpenuhi adalah persis pertanyaan saya. Apakah Anda menulis tes terpisah untuk itu? Atau hanya berasumsi bahwa tes akan pecah jika kondisi ini tidak benar? Bagaimana dengan situasi ketika setup tidak "serempak" buruk, hanya sedikit mati?
Ryszard Szopa

2
Tes Anda akan gagal jika kondisi awal tidak benar, itulah intinya. Saat dalam keadaan A, Anda mengharapkan hasil B. Jika Anda tidak memiliki status A, tes harus gagal. Pada titik itu Anda dapat menyelidiki mengapa gagal, kondisi awal yang buruk atau tes yang buruk, tetapi harus gagal dalam kedua kasus. Bahkan jika itu adalah, seperti yang Anda katakan, "sedikit off" (yaitu "A" => "B", "a" => "b", tetapi tidak pernah "a" => "B"atau tes Anda buruk).
dr Hannibal Lecter

19

Salah satu taktik adalah menulis tes sebelum kode itu diuji, dan memastikan tes gagal terlebih dahulu karena alasan yang tepat. Jika Anda menggunakan TDD, Anda harus mendapatkan setidaknya tingkat pengujian tes ini.

Cara yang lebih lengkap untuk menguji kualitas suite uji adalah dengan menggunakan pengujian mutasi .


2
Dan bahwa tes Anda gagal karena alasan yang tepat .
Frank Shearar

@ Jujur - Ya. Saya akan menambahkan itu ke jawabannya.
Don Roby

Dan Anda menambahkan tes baru untuk menguji perilaku baru. Jangan menambah tes yang ada.
Huperniket

@ DonRoby, Sudahkah Anda menemukan pengujian mutasi bermanfaat dalam praktik? Kekurangan apa yang Anda temukan dalam kasus pengujian Anda dengan itu?
dzieciou

4

Untuk # 1 dan # 3: Tes unit tidak boleh mengandung logika apa pun, jika Anda melakukannya, Anda mungkin menguji lebih dari satu hal dalam pengujian unit Anda. Salah satu praktik terbaik untuk pengujian unit adalah dengan hanya memiliki satu tes per tes unit.

Tonton video ini oleh Roy Osherove untuk mempelajari lebih lanjut tentang cara menulis unit test dengan baik.


iklan # 3 - Saya setuju bahwa tes harus sesederhana mungkin, dan tidak boleh mengandung logika apa pun. Namun, pikirkan tentang tahap persiapan tes, ketika Anda membuat objek yang dibutuhkan. Anda dapat membuat objek yang sedikit salah. Ini adalah jenis masalah yang saya pikirkan.
Ryszard Szopa

Ketika Anda mengatakan 'benda yang sedikit salah', maksud Anda keadaan objek tidak benar atau desain objek yang sebenarnya tidak benar? Untuk keadaan objek Anda mungkin bisa menulis tes untuk memeriksa validitasnya. Jika desain salah maka pengujian harus gagal.
Piers Myers

3

Dalam hal # 1 - saya pikir itu ide yang baik untuk memasangkan / meninjau kode untuk sisi ini. Sangat mudah untuk membuat anggapan atau hanya membuat kesalahan, tetapi jika Anda harus menjelaskan apa yang dilakukan tes Anda, apa intinya, Anda lebih mungkin untuk mengambil jika Anda membidik target yang salah.


2

Harus ada titik ketika seseorang harus berhenti mencoba unit test. Harus tahu kapan harus menggambar garis. Haruskah kita menulis kasus uji untuk menguji kasus uji? Bagaimana dengan test case baru yang ditulis untuk menguji test case? Bagaimana kita menguji mereka?

if (0 > printf("Hello, world\n")) {
  printf("Printing \"Hello, world\" failed\n");
}

Sunting: Diperbarui dengan penjelasan seperti yang disarankan oleh komentar.


-1 Apa? Ini sepertinya tidak memiliki relevansi.
alternatif

2
Harus ada titik ketika seseorang harus berhenti mencoba unit test. Harus tahu kapan harus menggambar garis. Haruskah kita menulis kasus uji untuk menguji kasus uji? Bagaimana dengan test case baru yang ditulis untuk menguji test case? Bagaimana kita mengujinya?
aufather

2
Proses Otak menaikkan EInfiniteRecursion saat mencoba memperkirakan pernyataan Anda ...
Mason Wheeler

Ganti jawaban Anda dengan komentar Anda dan Anda akan mendapatkan +1
Catatan untuk memikirkan sendiri nama

3
Dalam semua keadilan, contoh Anda adalah seorang pria jerami. Anda sedang menguji subsistem printf () di pustaka C, bukan program yang memanggil printf (). Saya setuju, bagaimanapun, bahwa pada titik tertentu seseorang harus memecahkan pengujian tes rekursif.
Tim Post

2

Hei.
Anda harus ke aplikasi:

  • Produk anda
  • Tes Anda untuk produk itu.

Ketika Anda menjalankan tes terhadap produk Anda, Anda sebenarnya tidak tertarik dalam tes itu sendiri, tetapi dalam interaksi antara produk Anda dan tes Anda. Jika pengujian gagal, itu tidak mengatakan bahwa aplikasi memiliki bug. Dikatakan bahwa interaksi antara produk dan tes tidak berhasil . Sekarang adalah tugas Anda untuk menentukan apa yang salah. Itu bisa berupa:

  • aplikasi tidak berlaku seperti yang Anda harapkan (harapan ini dinyatakan dalam tes Anda)
  • aplikasi berperilaku benar, Anda hanya belum mendokumentasikan perilaku ini dengan benar (dalam tes Anda)

Bagi saya tes gagal bukanlah umpan balik sederhana, bahwa ini dan itu salah . Ini adalah indikator bahwa ada ketidakkonsistenan, dan saya perlu memeriksa keduanya untuk memeriksa apakah ada yang salah. Pada akhirnya saya bertanggung jawab untuk memverifikasi bahwa aplikasi itu benar, tes hanyalah alat untuk menyoroti area yang mungkin perlu diperiksa.

Tes hanya memeriksa beberapa bagian aplikasi. Saya menguji aplikasi, saya menguji tes.


2

Tes seharusnya tidak "cukup pintar" untuk menyembunyikan bug.

Kode yang Anda tulis mengimplementasikan serangkaian spesifikasi. (Jika X maka Y, kecuali Z dalam kasus Q, dll, dll). Semua tes yang harus dicoba untuk diselesaikan adalah untuk menentukan bahwa X benar-benar Y kecuali Z dalam kasus Q. Ini berarti semua tes yang harus dilakukan adalah pengaturan X dan memverifikasi Y.

Tapi itu tidak mencakup semua kasus, Anda mungkin mengatakan, dan Anda akan benar. Tetapi jika Anda membuat tes "pintar" cukup untuk mengetahui bahwa X seharusnya hanya oleh Y jika tidak Z maka Anda pada dasarnya menerapkan kembali logika bisnis dalam pengujian. Ini bermasalah karena alasan kami akan masuk sedikit lebih dalam di bawah ini. Anda seharusnya tidak meningkatkan cakupan kode dengan membuat tes pertama Anda "lebih pintar", Anda harus menambahkan tes bodoh kedua yang menetapkan X dan Z dan memverifikasi Q. Dengan cara itu Anda akan memiliki dua tes, satu yang mencakup kasus umum ( kadang-kadang juga dikenal sebagai jalan bahagia) dan satu yang menutupi tepi kasus sebagai tes terpisah.

Ada sejumlah alasan untuk ini, pertama dan terutama adalah bagaimana Anda menentukan apakah tes gagal disebabkan oleh bug dalam logika bisnis atau bug dalam tes? Jelas jawabannya adalah bahwa jika tes sesederhana mungkin mereka sangat tidak mungkin menyembunyikan bug. Jika Anda berpikir tes Anda perlu pengujian maka Anda menguji salah .

Alasan lain termasuk bahwa Anda hanya mereplikasi upaya (seperti yang telah saya sebutkan, menulis tes yang cukup pintar untuk menjalankan semua kemungkinan dalam satu tes pada dasarnya mereplikasi logika bisnis yang Anda coba uji di tempat pertama), jika persyaratan berubah maka tes harus mudah diubah untuk mencerminkan persyaratan baru, tes berfungsi sebagai semacam dokumentasi (mereka adalah cara formal untuk mengatakan apa spesifikasi unit yang diuji), dan sebagainya.

TL: DR: Jika tes Anda perlu pengujian Anda salah melakukannya. Tulis tes bodoh .


0

Bukan jawaban (saya tidak memiliki hak istimewa untuk berkomentar), tetapi bertanya-tanya apakah Anda lupa alasan lain untuk mengembangkan kasus uji ...
Setelah Anda mengetahui semua bug dalam tes, Anda dapat regresi menguji aplikasi Anda dengan mudah. Suite tes otomatis akan membantu Anda menemukan masalah lebih awal, sebelum integrasi. Perubahan pada persyaratan relatif lebih mudah untuk diuji, karena perubahan tersebut dapat menjadi versi yang lebih baru, versi yang diubah dari kasus uji lama yang lulus, dan kasus yang lebih lama tetap mengalami kegagalan.


0

Jawaban singkat: Kode produksi menguji tes .

Bandingkan ini dengan model kredit / debit yang digunakan dalam ekonomi. Mekaniknya sangat sederhana - Jika kredit berbeda dari debit ada sesuatu yang salah.

dia juga berlaku untuk unit test - Jika tes gagal itu menunjukkan ada sesuatu yang salah. Mungkin kode produksi, tetapi mungkin juga kode uji! Bagian terakhir ini jika penting.

Perhatikan bahwa jenis Anda (1) bug tidak dapat ditemukan oleh unit test. Untuk menghindari bug jenis ini, Anda memerlukan alat lain.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.