Membuat Tes Unit pada lapisan CRUD Aplikasi, bagaimana saya bisa membuat tes independen?


14

Jadi saya mencoba untuk membuat Tes Unit saya sebagai oleh-buku-mungkin, tetapi menjadi merepotkan ketika saya menguji beberapa metode Tambahkan / Hapus sederhana.

Untuk metode add, pada dasarnya saya harus membuat objek dummy dan menambahkannya, kemudian setelah tes berhasil, saya harus menghapus objek dummy.

Dan untuk tes hapus, saya jelas harus membuat objek dummy sehingga saya bisa menghapusnya.

Seperti yang Anda lihat jika satu tes gagal, yang lain juga akan gagal, karena keduanya sama-sama diperlukan.

Sama dengan sistem di mana Anda perlu menulis tes yang "Membatalkan Pesanan" ... yah beberapa pesanan palsu akan diperlukan untuk membatalkan terlebih dahulu, bukankah ini bertentangan dengan pedoman pengujian unit?

Bagaimana kasus seperti ini dimaksudkan untuk ditangani?


Anda mungkin juga ingin melihat pertanyaan ini: programmers.stackexchange.com/questions/115455/…
Guven

Jawaban:


13

Nah, tidak ada yang salah dengan apa yang Anda lakukan. Beberapa tes dapat mencakup kode yang sama; itu hanya berarti bahwa satu masalah akan menyebabkan beberapa tes gagal. Yang ingin Anda hindari adalah tes yang tergantung pada hasil tes lain. Yaitu, tes hapus Anda bergantung pada uji tambah yang sudah berjalan, dan jika Anda menjalankan tes hapus sebelum tes tambahan, itu akan gagal. Untuk menghindari masalah itu, pastikan bahwa Anda memiliki "papan tulis kosong" pada awal setiap tes, sehingga apa yang terjadi dalam tes yang diberikan tidak dapat mempengaruhi tes berikutnya.

Cara terbaik untuk melakukannya adalah dengan menjalankan tes terhadap basis data dalam memori.

Dalam uji tambah Anda, buat database kosong, tambahkan objek, dan nyatakan bahwa itu memang telah ditambahkan.

Dalam tes hapus Anda, buat database dengan objek yang akan Anda hapus di dalamnya. Hapus objek, dan nyatakan bahwa itu telah dihapus.

Buang database dalam kode tear-down Anda.


Database dalam memori hanya cepat (dalam memori) dan sederhana (dalam proses). Anda bisa melakukan ini dengan penyimpanan data apa pun.
Paul Draper

3

Gunakan transaksi.

Jika Anda menggunakan database yang mendukung transaksi, maka jalankan setiap tes dalam transaksi. Kembalikan transaksi pada akhir tes. Kemudian setiap tes akan membiarkan database tidak berubah.

Ya, untuk membatalkan pesanan, Anda harus membuatnya terlebih dahulu. Tidak apa-apa. Tes pertama akan membuat pesanan, lalu membatalkannya, lalu memverifikasi bahwa pesanan dibatalkan.


Cintai ide ini. Diimplementasikan dengan efek besar hari ini.
pimbrouwers

3

Anda melakukannya dengan baik. Satu-satunya prinsip dasar pengujian unit adalah untuk mencakup setiap jalur kode yang Anda miliki, sehingga Anda dapat yakin bahwa kode Anda melakukan apa yang seharusnya dilakukan, dan terus melakukannya setelah perubahan dan perbaikan. Menjaga unit tes kecil, sederhana dan satu tujuan adalah tujuan yang bermanfaat, tetapi itu tidak mendasar. Memiliki tes yang memanggil dua metode terkait API Anda tidak dengan sendirinya dipertanyakan, pada kenyataannya, seperti yang Anda tunjukkan, seringkali diperlukan. Kelemahan dari melakukan tes redundan adalah hanya karena mereka membutuhkan lebih banyak waktu untuk menulis, tetapi karena hampir semua hal dalam pengembangan, ini adalah trade-off yang harus Anda lakukan setiap saat, dan solusi terbaik hampir tidak pernah menjadi salah satu poin ekstrem.


2

Teknik pengujian perangkat lunak sangat bervariasi, dan semakin Anda mendidik diri sendiri tentang hal itu, Anda akan mulai melihat banyak panduan yang berbeda (dan terkadang saling bertentangan). Tidak ada 'buku' tunggal untuk dilewati.

Saya pikir Anda berada dalam situasi di mana Anda telah melihat beberapa panduan untuk tes unit yang mengatakan hal-hal seperti

  • Setiap tes harus berdiri sendiri, dan tidak terpengaruh oleh tes lain
  • Setiap unit tes harus menguji satu hal, dan hanya satu hal
  • Tes unit tidak boleh mengenai database

dan seterusnya. Dan semua itu benar, tergantung pada bagaimana Anda mendefinisikan 'unit test' .

Saya akan mendefinisikan 'unit test' sebagai sesuatu seperti: "tes yang melatih satu fungsi untuk satu unit kode, terisolasi dari komponen dependen lainnya".

Di bawah definisi itu, apa yang Anda lakukan (jika perlu menambahkan catatan ke database sebelum Anda dapat menjalankan tes) sama sekali bukan 'unit test', tetapi lebih dari apa yang biasa disebut 'tes integrasi'. (Tes unit yang sebenarnya, menurut definisi saya, tidak akan mengenai database, jadi Anda tidak perlu menambahkan catatan sebelum menghapusnya.)

Tes integrasi akan menjalankan fungsionalitas yang menggunakan banyak komponen (seperti antarmuka pengguna dan database), dan panduan yang akan berlaku untuk pengujian unit tidak harus berlaku untuk pengujian integrasi.

Seperti yang disebutkan orang lain dalam jawaban mereka, apa yang Anda lakukan tidak selalu salah bahkan jika Anda melakukan hal-hal yang bertentangan dengan beberapa panduan tes unit. Sebagai gantinya, cobalah untuk beralasan tentang apa yang sebenarnya Anda uji dalam setiap metode pengujian, dan jika Anda menemukan bahwa Anda memerlukan banyak komponen untuk memenuhi pengujian Anda, dan beberapa komponen memerlukan pra-konfigurasi, maka lakukan dan lakukan.

Tetapi yang paling penting, pahamilah bahwa ada banyak jenis tes perangkat lunak (tes unit, tes sistem, tes integrasi, tes eksplorasi, dll.), Dan jangan mencoba menerapkan pedoman dari satu tipe ke yang lainnya.


Jadi apakah Anda mengatakan bahwa Anda tidak dapat menguji unit menghapus dari database?
ChrisF

Jika Anda mencapai basis data, itu (menurut definisi) adalah tes integrasi, bukan tes unit. Jadi, dalam pengertian itu, tidak. Anda tidak dapat 'unit test' menghapus dari database. Apa yang dapat Anda uji unit adalah bahwa ketika kode yang Anda uji diminta untuk menghapus beberapa data, ia berinteraksi dengan modul akses data dengan benar.
Eric King

Tetapi intinya adalah, beberapa orang mungkin mendefinisikan 'unit test' secara berbeda, jadi kita harus berhati-hati ketika menerapkan pedoman 'unit test', karena pedoman mungkin tidak berlaku seperti yang kita pikirkan.
Eric King

1

Inilah sebabnya mengapa salah satu pedoman lainnya adalah menggunakan antarmuka. Jika metode Anda mengambil objek yang mengimplementasikan antarmuka alih-alih implementasi kelas tertentu, Anda bisa membuat kelas yang tidak bergantung pada sisa basis kode.

Alternatif lain adalah dengan menggunakan kerangka kerja mengejek. Ini memungkinkan Anda untuk dengan mudah membuat jenis objek boneka yang dapat dilewatkan ke metode yang Anda uji. Ada kemungkinan bahwa Anda mungkin harus membuat beberapa implementasi rintisan untuk kelas dummy, tetapi masih menciptakan pemisahan dari implementasi aktual dan apa yang terkait dengan tes.


1

Seperti yang Anda lihat jika satu tes gagal, yang lain juga akan gagal, karena keduanya sama-sama diperlukan.

Begitu?

... bukankah ini bertentangan dengan pedoman pengujian unit?

Tidak.

Bagaimana kasus seperti ini dimaksudkan untuk ditangani?

Beberapa tes dapat dilakukan secara independen dan semuanya gagal karena bug yang sama. Itu sebenarnya normal. Banyak tes mungkin - secara tidak langsung - menguji beberapa fungsi umum. Dan semua gagal ketika fungsi umum rusak. Tidak ada yang salah dengan itu.

Tes unit didefinisikan sebagai kelas dengan tepat sehingga mereka dapat dengan mudah berbagi kode, seperti catatan boneka umum yang digunakan untuk menguji pembaruan dan menghapus.


1

Anda dapat menggunakan kerangka tiruan atau menggunakan 'lingkungan' dengan basis data dalam memori. Yang terakhir adalah kelas di mana Anda dapat membuat semua yang Anda butuhkan untuk membuat lulus ujian, sebelum ujian berjalan.

Saya lebih suka yang terakhir - pengguna dapat membantu Anda memasukkan beberapa data sehingga tes Anda menjadi paling dekat dengan dunia nyata.


Benar - tetapi Anda tidak benar-benar menguji koneksi database nyata di sini. Kecuali Anda berasumsi bahwa itu akan berhasil - tetapi anggapan itu berbahaya.
ChrisF
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.