Apakah saya Unit Testing atau Integration Testing, Prosedur Tersimpan saya?

8

Saya memiliki banyak kesempatan baru-baru ini di mana saya harus memelihara prosedur dan fungsi yang tersimpan kompleks. Ini sudah rusak, biasanya dalam cara yang cukup halus - ada beberapa kesempatan di mana Anda akan memanggil SP dengan parameter yang valid dan itu hanya tidak berfungsi.

Solusi saya adalah mengembangkan kerangka kerja yang mengeksekusi prosedur tersimpan di dalam transaksi, setelah menginisialisasi database ke kondisi awal yang saya butuhkan, kemudian menguji untuk hasil yang diharapkan, juga dalam transaksi yang sama. Transaksi dibatalkan pada akhir tes.

Ini telah bekerja dengan sangat baik. Tetapi beberapa orang akan menyebutnya "pengujian integrasi" karena melibatkan integrasi dengan database. Saya menyebutnya unit testing, karena saya menguji masing-masing komponen dan kasus uji individual untuk komponen-komponen itu, dan karena saya sepenuhnya mengendalikan keadaan awal basis data.

Tapi di mana garis harus ditarik? Apakah ini pengujian integrasi atau pengujian unit? Adakah alasan praktis mengapa tes semacam ini adalah ide yang buruk? Jika ini "hanya" pengujian integrasi, apakah ada yang punya saran tentang bagaimana melakukan "unit test" yang sebenarnya pada prosedur yang tersimpan ini?


Perbarui, 3 1/2 tahun kemudian. Pada proyek saya saat ini, saya sudah mulai menggunakan tes unit SSDT, dengan sukses, meskipun mereka bisa lebih baik. Lihat Memverifikasi Kode Basis Data dengan Menggunakan Tes Unit SQL Server . Ini biasanya menyebarkan proyek database ke instance Anda dari SQL Server LocalDB, jadi ini menghilangkan pertanyaan tentang lingkungan database yang mempengaruhi pengujian. Saya mengisi database dengan data yang diperlukan selama Pra-Tes, yang menghilangkan pertanyaan tentang konten database. Bahkan, saya menggunakan pernyataan MERGE untuk melakukan ini, memastikan bahwa data apa pun yang saya tidak perlukan untuk pengujian saat ini dihapus, dimasukkan atau diperbarui dari database sebelum pengujian. Mereka memang memiliki masalah:

  • Mereka tidak cepat
  • Tidak mungkin menggunakan kembali kondisi pengujian
  • Tidak mungkin untuk menggunakan kembali pra-tes (kecuali jika Anda membuatnya umum untuk semua tes dalam suatu proyek)
  • Antarmuka pengguna dapat ditingkatkan

Salah satu alasan untuk masalah di atas adalah bahwa saya belum mengeluh tentang mereka. Saya sarankan siapa pun yang tertarik harus mencoba fitur ini, dan kemudian mengeluh tentang hal itu. Begitulah cara perbaikan dilakukan.

John Saunders
sumber
1
Mengapa itu menjadi sebuah oxymoron ?
doppelgreener
Pertanyaan bagus. Apa pendapat Anda tentang mengubah judul? Mungkin kira-kira seperti ini: "Bagaimana cara menguji prosedur yang tersimpan"
Matthew Rodatus
@Matthew: "diedit secara kolaboratif"
John Saunders

Jawaban:

7

Maksud dari pengujian unit bukanlah untuk membuat peri tes unit sihir datang dan memvalidasi pendapat Anda. Ini untuk menguji blok bangunan terkecil, paling sederhana dari sistem Anda, sehingga Anda tidak menguji beberapa fungsi yang lebih luas dan tersandung karena sesuatu tidak bekerja seperti yang Anda pikirkan. Jadi, bisakah Anda memecah ini lebih lanjut? Saya pikir Anda tidak bisa, dalam hal ini:

(a) Kedengarannya seperti tes unit bagi saya, dan (b) Tidak masalah apakah itu tes unit atau tidak, karena tes ini menguji apa yang Anda butuhkan, yang merupakan titik menggunakan tes unit pada awalnya!

Jika Anda merasa prosedurnya terlalu rumit, Anda mungkin ingin memecahnya sendiri menjadi bagian-bagian yang lebih kecil (dalam prosedur basis data atau dalam kode), tetapi untuk melakukan itu Anda ingin melakukan tes ini terlebih dahulu!

Jack V.
sumber
7

Pengujian unit menurut definisi berkisar pada pengujian "unit" kode di lingkungan atau platform yang berjalan. Platform yang Anda gunakan adalah database sehingga Anda harus menggunakannya, itu tidak integratif.

Pertanyaan yang lebih baik adalah mengapa Anda peduli. Selama ini otomatis dan menambah nilai, peduli apakah tes Anda dalam tes unit, tes penerimaan, tes asap, atau tes fungsional?

Di pekerjaan saya, kami saat ini memanfaatkan kerangka pengujian unit untuk melakukan Acceptance Test Driven Development (ATDD). Beberapa tes bersifat integratif, beberapa tidak. Hampir tidak ada dari mereka yang merupakan unit test, tetapi kami tidak peduli selama:

  • tes menambah nilai
  • tes tidak memiliki kegagalan atau keberhasilan yang salah (sebagian besar bersifat deterministik)
  • tes otomatis

Memperbarui

Ini semua masalah biaya dan manfaat. Semakin banyak bagian yang bergerak Anda semakin tinggi risiko memiliki tes non-deterministik. Tes unit klasik memiliki jumlah bagian bergerak yang paling sedikit, dan karena itu memiliki peluang paling kecil untuk menjadi non deterministik. Imbalannya adalah Anda tidak menguji titik integrasi (kode, database, fs, jaringan, dll). Semua ini berguna untuk dicakup dalam tes, selama risiko kegagalan atau kesuksesan palsu cukup rendah.

Tes memberikan nilai pada apa yang tidak mereka lakukan. Kuncinya adalah seberapa sering Anda akan mengalami kegagalan dan kesuksesan palsu. Jika saya memiliki kesalahan palsu selama 2 jam setiap bulan karena itu adalah jendela pemeliharaan untuk jaringan, maka nilai tes jelas. Ketika mereka gagal jelas ada sesuatu yang salah dengan sumber daya jaringan, bukan tes tertentu. Dan sekarang Anda memiliki cakupan pengujian yang lebih tepat karena Anda menguji titik integrasi tersebut.

dietbuddha
sumber
Salah satu alasan saya peduli adalah bahwa beberapa tempat akan mengeluh jika tes unit Anda tidak "tes unit" menurut definisi mereka. Alasan lain adalah bahwa hal itu muncul dalam komentar pada " Apakah Ada Jalan Tengah? (Pengujian Unit vs. Pengujian Integrasi) "
John Saunders
@John Berdasarkan jawaban @ dietbuddha dan penelitian yang saya baca: Karena Anda menggunakan tumpukan jaringan dan server DB, tes Anda tidak "sebagian besar bersifat deterministik." Mereka tidak boleh diklasifikasikan sebagai unit test. Tapi tentu saja itu hanya pendapat saya.
Matius Rodatus
1
@ Matthew: Saya tidak tahu platform apa yang Anda kembangkan, tapi saya jamin Anda bahwa tumpukan jaringan dan server database yang saya gunakan tidak terlalu sering gagal. Bahkan, kegagalan komponen ini dapat diabaikan untuk tujuan pengujian.
John Saunders
@John Saunders: jawaban yang diperbarui
dietbuddha
2

Saya pikir itu tergantung dari mana data berasal. Jika Anda membuat kondisi pengujian dalam awalan tes, saya pikir masuk akal untuk menyebutnya tes unit. Kalau tidak, Anda masuk ke argumen rewel tentang apa yang dianggap sebagai "sudah ada" untuk tes unit. Sama seperti tes unit database Anda bergantung pada keberadaan tabel database dan seterusnya, tes unit di luar database bergantung pada hal-hal seperti definisi kelas dan sering kali contoh dari clssses tersebut. Itu tidak buruk, itu realistis.


sumber
1

Saya akan menganggap itu sebagai pengujian integrasi:

  1. Ini jauh lebih lambat daripada tes unit seharusnya.
  2. Itu tidak menjalankan unit atom tunggal kode - ia menjalankan prosedur Anda, server database, tumpukan jaringan, dll.
  3. Tidak akan mudah untuk mendeteksi di mana kesalahan terjadi jika tes gagal. Anda harus melihat setiap kegagalan secara manual untuk melihat apakah itu kegagalan sistem eksternal, atau kode Anda.

Namun, tes seperti yang Anda gambarkan sangat berharga untuk dimiliki. Kami baru-baru ini mulai menambahkan tes begitu saja, untuk menguji prosedur tersimpan yang tidak mungkin diuji secara manual di lingkungan tertentu. Saya tidak tahu cara lain untuk memiliki tes otomatis untuk prosedur tersimpan.

Jadi, tes ini adalah ide bagus, tetapi menyebutnya tes integrasi - gunakan kategori tes atau akhiran nama untuk membedakannya dari tes unit biasa. Dengan cara ini, Anda dapat menandai kegagalan pengujian integrasi secara berbeda dari kegagalan pengujian unit dalam otomasi bangunan Anda.

Matthew Rodatus
sumber
@ Matthew: Saya tidak menguji server database atau tumpukan jaringan, lebih dari saya menguji .NET BCL atau CLR. Juga, saya tidak mengalami kesulitan sama sekali untuk menemukan kegagalan. Mungkin saya harus memberikan contoh yang lebih rinci tentang jenis tes yang saya maksud.
John Saunders
@ John Ketika saya berkata "uji server database dan tumpukan jaringan," Maksud saya Anda sedang menguji kode apa pun yang Anda gunakan. .NET BCL / CLR harus memiliki tiket ke unit test - Anda tidak dapat menulis kode tanpa itu! Tapi, tes yang berbicara ke server database juga dilakukan (yaitu pengujian) server dan jaringan. Saya kira saya harus bertanya: Bagaimana Anda menjalankan tes prosedur Anda? Dari metode pengujian unit C #? Script SQL? Bagaimana Anda mengotomatiskan pelaporan hasil?
Matthew Rodatus
@ Matthew: tes NUnit normal dari metode di kelas saya menggunakan .NET Framework, menurut definisi Anda. Bukan milik saya, karena saya berasumsi bahwa .NET berfungsi. Demikian pula, saya mengasumsikan bahwa SQL Server berfungsi, dan bahwa SqlCommandkelas berfungsi, dan bahwa transport TCP berfungsi. Saya belum salah tentang itu.
John Saunders
1
@ Matthew: jika SQL Server dan built-in transports dan fitur-fiturnya tidak berfungsi, maka saya punya masalah yang lebih besar daripada apakah saya pengujian unit atau pengujian integrasi. Saya biasanya berasumsi bahwa OS bekerja juga, dan bahwa kecepatan cahaya lebih atau kurang konstan dalam bingkai tes saya beroperasi.
John Saunders
1
@ John, saya kira Anda tidak mengerti maksud saya, tapi oh well.
Matthew Rodatus
0

Apakah ini pengujian integrasi atau pengujian unit?

Di mana tes berjalan? Pada database atau melalui test harness berbasis kode (JUnit)?

Pada database maka kemungkinan unit test (karena mandiri), test harness seperti JUnit kemudian terhubung ke database eksternal dan dengan demikian tes integrasi.

Jika ini "hanya" pengujian integrasi

Mengapa mengutip? Tes integrasi bukanlah sejenis binatang buas yang tidak boleh Anda lakukan.

apakah ada yang punya saran tentang bagaimana melakukan "unit test" yang sebenarnya pada prosedur yang tersimpan ini?

Saya biasanya menemukan satu-satunya unit yang masuk akal untuk prosedur tersimpan adalah kode panggilan dan prosedur. Jadi saya integrasi menguji set lengkap dalam serangkaian tes yang terlihat seperti tes unit.

Pertanyaan yang lebih baik adalah mengapa Anda peduli [tentang nama].

Karena memungkinkan Anda untuk membagi tes. Tes integrasi membutuhkan waktu lebih lama untuk dijalankan, memerlukan pengaturan tambahan dan kemungkinan akses ke sumber daya yang dibagikan oleh banyak tes (misalnya database).

1) Kode panggilan akan memiliki tes unit tambahan jika diperlukan.

mlk
sumber
Tidak ada pengaturan tambahan. Semua pengaturan dalam tes itu sendiri. Juga, tes ini cukup cepat. Persiapan dalam pembukaan tes sejauh ini tidak diperlukan untuk melakukan lebih dari menghapus 50 baris dan kemudian memasukkan selusin lainnya.
John Saunders
Ini memulai database jika seseorang tidak berjalan?
mlk
"Mulai basis data"? Tidak, tes menggunakan string konfigurasi yang disimpan dalam file konfigurasi untuk tes, dan satu menganggap bahwa setelah string konfigurasi yang tepat ditentukan, bahwa itu akan terus merujuk ke database yang valid dalam server database yang valid. Di dunia yang ideal, tes ini dapat berjalan setelah penyebaran (pembuatan) contoh baru dari database, menggunakan DDL saat ini, juga disimpan dalam kontrol sumber. Kami sedang berupaya mencapai cita-cita itu.
John Saunders
Ini adalah cita-cita yang bagus untuk dicapai. Saya telah bekerja ke arah yang sama untuk beberapa waktu. Maksud saya adalah Anda memiliki tugas memulai (memulai database). Anda dapat (dan harus) mendapatkan tes Anda agar tidak gagal (Menegaskan. Tidak Konklusif dalam MSTest berbicara) jika tugas belum dilakukan. Area pengujian ini merupakan area abu-abu dari unit testing. Tulislah tes yang mirip Tes Unit, tetapi terimalah tes integrasi.
mlk
1
Saya tidak yakin apa yang Anda maksud dengan memulai database. Dalam "dunia ideal" saya, penyebaran contoh baru yang kosong dari basis data akan menjadi bagian dari pembuatan otomatis, bukan bagian dari pengujian.
John Saunders
-1

Microtest adalah istilah yang berguna yang dapat membantu Anda menghindari perdebatan tentang terminologi dan apakah tes Anda merupakan tes unit atau tidak.

Definisi umum dari unit-test mencakup bahwa sistem yang diuji adalah unit fungsionalitas kecil dan Anda harus dapat menjalankan semua tes terhadapnya dalam memori, tanpa bantuan dari sistem file, jaringan, atau mesin basis data . Jika Anda membutuhkan mesin database aktual untuk menjalankannya, maka itu bukan tes unit.

Sementara definisi ini bekerja dengan sangat baik untuk semua lapisan aplikasi, itu tidak sangat membantu untuk lapisan akses basis data terbawah. Kita harus mengakui bahwa itu istimewa. Jika tes Anda hanya menguji unit kecil dari fungsi penyimpanan / pengambilan / perbarui / hapus, maka pengujian Anda jelas sama berharganya dengan tes unit "ketat" yang ditulis terhadap lapisan atas sistem Anda.

azheglov
sumber
Di sinilah kontroversi terjadi: Saya tidak menguji DAL: Saya menguji prosedur dan fungsi yang tersimpan dalam database itu sendiri. Jika DAL sesederhana hanya mengatur parameter dan kemudian memanggil SP atau fungsi atau SELECT, maka saya tidak repot-repot mengujinya.
John Saunders