Bagaimana saya harus menguji kode TEST saya?

22

Salah satu dari beberapa hal yang disetujui sebagian besar pengembang perangkat lunak adalah Anda tidak harus bergantung pada kode untuk bekerja dengan benar kecuali Anda mengujinya. Jika Anda tidak mengujinya, mungkin ada bug tersembunyi yang hanya akan menyebabkan Anda bekerja lebih keras.

Saya mengerti bagaimana menguji kode normal saya, tetapi bagaimana saya harus menguji kode pengujian saya untuk memastikannya dapat secara efektif menemukan dan melaporkan kesalahan ketika mereka ada? Saya pribadi sudah cukup bodoh untuk menulis kasus-kasus ujian yang keliru yang seharusnya lulus ketika seharusnya tidak, sehingga mengalahkan tujuan dari tes penulisan saya di tempat pertama. Untungnya, saya menemukan dan memperbaiki kesalahan dalam waktu, tetapi menurut mantra pengujian sepertinya tidak ada rangkaian tes yang akan lengkap tanpa memiliki serangkaian tes sendiri untuk memastikan itu berfungsi.

Bagi saya, cara terbaik untuk melakukan ini adalah dengan memastikan tes gagal untuk kode buggy. * Jika saya menghabiskan 2 menit secara bergantian menambahkan bug ke kode dan memastikan gagal, saya harus memiliki tingkat kepercayaan yang dapat diterima bahwa tes 'berhasil'. Ini membawa saya ke pertanyaan kedua: Apa cara yang baik untuk memperkenalkan bug untuk memastikan bahwa mereka tertangkap oleh kasus uji? Jika saya hanya mengomentari pernyataan secara acak, pastikan cabang yang salah if-elsedijalankan dengan meniadakan kondisinya, dan mengubah urutan eksekusi kode dengan efek samping, dll., Sampai saya puas tes saya akan menangkap sebagian besarbug umum? Bagaimana pengembang profesional memvalidasi bahwa tes mereka benar-benar melakukan apa yang seharusnya mereka lakukan? Apakah mereka hanya menganggap tes itu berhasil, atau apakah mereka meluangkan waktu untuk mengujinya juga? Jika demikian, bagaimana mereka menguji tes?

Saya tidak menyarankan orang-orang harus menghabiskan begitu banyak waktu untuk menguji tes mereka dan kemudian menguji tes untuk tes mereka sehingga mereka tidak pernah benar-benar menulis kode asli, tetapi saya telah melakukan hal-hal yang cukup bodoh yang saya rasa saya bisa mendapat manfaat dari sedikit dari 'pengujian meta', dan ingin tahu tentang cara terbaik untuk melakukannya. : D

* Saya dapat memeriksa untuk melihat apakah tes lulus ketika menguji kode 'bebas bug', tetapi menggunakan kode sebagai spek untuk pengujian tampaknya cukup terbelakang ...

Gordon Gustafson
sumber
Kedengarannya seperti Anda tidak memiliki kepercayaan diri dalam tes unit Anda - kemungkinan besar karena Anda tidak memiliki banyak pengalaman dalam tes menulis? Dalam hal ini tidak masuk akal untuk menulis lebih banyak tes dan mengharapkan hasil yang berbeda. Terus lakukan apa yang Anda lakukan, selesaikan yang Anda bisa (uji kegagalan dan keberhasilan) dan segera unit test Anda akan mulai membayar sendiri - dan kepercayaan Anda pada mereka akan tumbuh.
MattDavey
Kemungkinan rangkap dari Bagaimana cara menguji tes?
nyamuk
Sebelum menggunakan lebih banyak alat, gunakan alat Anda yang sebenarnya dengan lebih baik . Menulis lebih sedikit tes, tetapi tes tertulis lebih efisien dan lebih baik. Anda tidak bisa mempercayai sesuatu yang tidak Anda mengerti.
Steve Chamaillard

Jawaban:

16

Alur standar untuk TDD adalah:

  1. Tulis tes yang gagal. (Merah)
  2. Buat perubahan kode terkecil yang membuatnya lulus (Hijau)
  3. Refactor (Menjaga tetap hijau)

Tes untuk tes Anda dalam hal ini adalah langkah 1 - memastikan bahwa tes gagal sebelum Anda membuat perubahan kode.

Tes lain yang saya suka adalah apakah Anda dapat menghapus beberapa kode dan mengimplementasikannya kembali dengan cara yang berbeda, dan pengujian Anda gagal setelah penghapusan tetapi bekerja dengan algoritma yang berbeda di tempat.

Seperti halnya semua hal, tidak ada peluru ajaib. Lupa menulis tes yang diperlukan sama mudahnya bagi pengembang untuk melakukan seperti lupa menulis kode. Setidaknya jika Anda melakukan keduanya, Anda memiliki peluang dua kali lebih banyak untuk menemukan kelalaian Anda.

Bringer128
sumber
4
Pembukuan ganda: Tes unit menguji kode produksi dan sebaliknya. Mereka adalah dua cara berbeda untuk menyatakan masalah yang sama. Seperti dalam pembukuan ganda, di mana Anda mencatat transaksi Anda dalam dua cara yang berbeda dan keduanya harus mendapatkan total yang sama.
EricSchaefer
Pertanyaannya adalah tentang masalah ketika langkah 2 membuat tes hijau meskipun kode masih bermasalah. Contoh sederhana: Anda memiliki fungsi yang harus mengembalikan pointer ke objek daftar yang tidak kosong. Tes Anda menguji apakah pointer nulldan gagal pada langkah 1. Anda membuat perubahan kode terkecil yang membuatnya lulus dengan mengembalikan daftar kosong. Tes sekarang "hijau" karena Anda memiliki dua bug.
Christian Hackl
@ChristianHackl pada tahap pengembangan itu adalah implementasi yang sempurna! Anda harus menambahkan satu (atau lebih) tes yang gagal pada awalnya untuk lebih menentukan perilaku yang diharapkan. Selanjutnya Anda menerapkannya, membuat tes ini hijau.
Andy
@Andy: Peduli untuk menguraikan bagaimana ini adalah implementasi yang sempurna ketika saya memiliki bug baik dalam kode dan dalam tes, dan satu membuat saya tidak memperhatikan yang lain? (Bug dalam kodenya adalah bahwa daftar kosong dikembalikan, dan bug dalam tes adalah bahwa saya memeriksa nulldan bukan untuk kosong.)
Christian Hackl
@ChristianHackl Anda benar menurut cek kosong. Itu, memang, harus dilakukan dalam ujian juga. Ketika Anda menerjemahkan persyaratan Anda ke pengujian, langkah demi langkah, ada sedikit ruang untuk bug. Kecuali saat Anda tidak mematuhi spesifikasi (seperti menghadap cek yang tidak kosong).
Andy
9

Salah satu pendekatan adalah Mutation Testing , menggunakan alat seperti Jester :

Jester membuat beberapa perubahan pada kode Anda, menjalankan tes Anda, dan jika tes lulus Jester menampilkan pesan yang mengatakan apa yang berubah

parsifal
sumber
4

Tes untuk tes? Jangan melewati jalan itu. Maka Anda mungkin perlu tes untuk tes untuk tes, dan kemudian tes untuk tes untuk tes untuk ... di mana Anda berhenti?

Alur pengujian biasa berjalan seperti ini, dan sebagai pengembang, Anda akan menghabiskan sebagian besar waktu Anda pada poin 1-3:

  1. Kode
  2. Tes unit
  3. Tes integrasi
  4. Sistem / otomatis lainnya
  5. QA / penguji manusia

Jika saya menghabiskan 2 menit secara bergantian menambahkan bug ke kode (...)

Kode Anda pada akhirnya akan "menumbuhkan" bug-nya sendiri, jangan buang waktu memperkenalkannya dengan tangan. Belum lagi, apakah hal yang Anda tahu tentang dimuka benar-benar bug? Bug akan datang, saya tidak akan khawatir tentang itu.

Jika saya hanya mengomentari pernyataan secara acak, pastikan cabang yang salah dari if-else dijalankan dengan meniadakan kondisinya (...)

Ini sebenarnya merupakan pendekatan yang layak untuk memverifikasi apakah Anda benar-benar menguji apa yang Anda pikir Anda lakukan. Saya tidak berpikir itu selalu baik karena menderita masalah yang sama seperti "test for test for test ..." hal: kapan Anda berhenti mengubah kode mengetahui kode yang Anda uji 100% berfungsi?

Ini juga baik untuk diingat tentang semua saran programmer pragmatis klasik waktu - Anda tidak akan membutuhkannya . Jadilah gesit, tulis tes dan kode untuk bug yang sebenarnya, sebagai gantinya untuk hipotesis yang mungkin atau mungkin tidak muncul.

km
sumber
3
Saya tidak khawatir tentang kode saya mengembangkan bug sendiri, saya khawatir tentang pengujian saya menangkap mereka ketika mereka terjadi. Jika tes saya salah, mereka tidak akan melakukan pekerjaan mereka dan saya akan berpikir bahwa saya telah menyingkirkan kelas bug tertentu ketika mereka benar-benar masih ada, hanya membuat pekerjaan saya lebih sulit karena saya melihat hasil tes yang tidak akurat (lulus ketika mereka harus gagal).
Gordon Gustafson
@CrazyJugglerDrummer: tes Anda tidak akan menangkap semua bug yang pasti. Mereka tidak melayani tujuan itu - ini adalah tempat QA masuk. Jika mereka melakukannya, itu berarti perangkat lunak bebas bug, kecuali perubahan kode sumber, yang belum pernah saya lihat.
km
3

Dengan konstruksi, kode fungsional dan kode uji diuji satu terhadap yang lain. Satu masalah tetap ada: kasus bug mode umum, ketika bug dalam kode fungsional disembunyikan oleh bug dalam kode uji. TDD tidak kebal terhadap efek ini. Inilah sebabnya mengapa pengujian biasanya dilakukan pada beberapa tingkatan oleh orang yang berbeda untuk mengurangi kemungkinan ini.

mouviciel
sumber
0

Anda menguji unit test Anda satu kali saat Anda menulisnya, di debugger. Kemudian Anda membiarkannya dan melupakannya. Tidak ada masalah di sini.

Pertimbangkan ini. Apa tujuan dari tes unit? Ini memberi tahu Anda ketika salah satu dari banyak perubahan yang akan Anda buat di program utama Anda secara tidak sengaja mengubah logika dalam program itu. Anda ingin memilikinya karena Anda tahu bahwa perubahan apa pun berpotensi merusak sesuatu. Itulah sebabnya tidak ada masalah jika Anda tidak menguji tes Anda: Anda tidak mengacaukan tes Anda sampai Anda dengan sengaja mengubah logika program Anda (yang akan mengharuskan Anda untuk meninjau kembali tes dan mengujinya sekali lagi), jadi Anda Tes tidak mungkin pecah secara tidak sengaja.

Martin Maat
sumber
-2

Ada pengujian mutasi yang mengevaluasi dan mengukur kesesuaian dan kualitas pengujian.

Kita dapat menggunakan ini untuk mengevaluasi "tes" itu sendiri.

Secara singkat, Kami dapat mengevaluasi pengujian kami (mis. TestA) dengan menguji TestA dapat menemukan perbedaan antara kode dan kode mutasinya (sangat mirip tetapi kode sedikit berbeda dengan kode asli).

Jika TestA tidak dapat menemukan perbedaan antara kode dan kode mutasinya, itu berarti bahwa TestA memiliki peraturan terlalu kasar untuk menguji kode asli.

Pemburu ayam
sumber