Saya memulai proyek baru, dan berusaha sangat keras untuk menggunakan TDD untuk menggerakkan desain. Saya sudah mendorong selama bertahun-tahun, dan akhirnya mendapat persetujuan untuk menghabiskan waktu ekstra pada proyek ini untuk menggunakannya sementara saya belajar bagaimana melakukannya dengan benar.
Ini adalah modul baru, untuk mengikat ke sistem yang ada. Saat ini, semua akses data terjadi melalui layanan web, yang sebagian besar hanyalah pembungkus tipis atas prosedur yang tersimpan dalam basis data.
Salah satu persyaratan adalah bahwa untuk toko tertentu, saya mengembalikan semua Pesanan Pembelian yang dianggap valid untuk aplikasi ini. PO dianggap valid jika tanggal pengiriman jatuh dengan kisaran tertentu dari tanggal pembukaan toko (ini untuk toko baru).
Sekarang, saya tidak bisa memasukkan logika ini dalam kode aplikasi, karena saya tidak akan mengembalikan satu juta PO hanya untuk mendapatkan selusin yang berlaku untuk dapat diterapkan ke toko ini mengingat kendala di atas.
Saya berpikir, saya bisa meneruskan rentang tanggal ke proc GetValidPOs, dan meminta mereka menggunakan nilai-nilai itu untuk mengembalikan PO yang valid. Tetapi, bagaimana jika kita menambahkan persyaratan lain untuk apa yang dianggap sebagai PO yang valid?
Dan bagaimana cara menguji ini dan memverifikasinya tetap berfungsi? Kami tidak menggunakan ORM, dan itu tidak mungkin terjadi. Dan saya tidak bisa memanggil DB dalam pengujian saya.
Aku terjebak.
Pikiran saya yang lain, adalah memiliki beberapa ejekan yang mengembalikan data yang valid, yang lain yang mengembalikan beberapa data buruk, dan membuat repositori lokal melempar pengecualian jika data buruk terjadi, dan menguji bahwa pengecualian dilemparkan jika data yang tidak valid dikembalikan oleh GetValidPOs proc (atau tiruan yang digunakan dalam pengujian).
Apakah ini masuk akal? Atau ada cara yang lebih baik?
UPDATE: Sepertinya saya bisa menggunakan EF. Sekarang saya hanya perlu mencari cara untuk menggunakannya, dan membuatnya dapat diuji, sementara masih bisa mengandalkan prosedur yang tersimpan, dan kesulitan memiliki data yang tersebar di beberapa database.
sumber
Jawaban:
Ini adalah kelemahan utama dari prosedur tersimpan di usia TDD. Mereka memiliki beberapa keuntungan nyata, bahkan sekarang, tetapi menurut definisi setiap tes yang menggunakan proc yang disimpan bukanlah tes unit; ini adalah tes integrasi terbaik.
Solusi yang biasa, dengan asumsi arsitektur tidak dapat berubah untuk menggunakan ORM sebagai gantinya, adalah tidak menempatkan tes ini di unit test suite; sebagai gantinya, letakkan tes dalam suite integrasi. Anda masih dapat menjalankan tes kapan pun Anda ingin memverifikasi itu berfungsi, tetapi karena biaya yang melekat dalam menyiapkan tes (menginisialisasi DB dengan data tes yang tepat) tinggi dan menyentuh sumber daya, agen unit-test build-bot Anda mungkin tidak memiliki akses ke, seharusnya tidak berada di unit test suite.
Anda masih dapat menguji kode unit yang membutuhkan data, dengan mengabstraksi apa pun yang tidak dapat Anda uji unit (kelas ADO.NET) menjadi kelas DAO yang dapat Anda tiru. Anda kemudian dapat memverifikasi bahwa panggilan yang diharapkan dilakukan dengan menggunakan kode dan mereproduksi perilaku dunia nyata (seperti tidak menemukan hasil) yang memungkinkan pengujian berbagai kasus penggunaan. Namun, pengaturan aktual dari SqlCommand untuk memanggil proc yang disimpan cukup banyak hal terakhir yang Anda bisa uji unit, dengan memutuskan pembuatan perintah dari eksekusi perintah dan mengejek pelaksana perintah. Jika ini kedengarannya seperti pemisahan yang banyak dari keprihatinan, bisa jadi itu; ingat, "tidak ada masalah yang tidak dapat diselesaikan dengan lapisan tipuan lainnya, kecuali karena memiliki terlalu banyak lapisan tipuan". Pada titik tertentu Anda harus mengatakan "cukup; Saya tidak bisa menguji unit ini, kami
Pilihan lain:
Uji proc yang disimpan menggunakan instance DBMS "berumur pendek" seperti SQLite. Biasanya lebih mudah untuk melakukan ini ketika menggunakan ORM, tetapi tes kemudian dapat dilakukan "di-memori" (atau dengan file database yang telah ditetapkan termasuk dengan test suite). Masih bukan unit test, tetapi dapat dijalankan dengan tingkat isolasi yang tinggi (DBMS adalah bagian dari proses yang sedang berjalan, dan bukan sesuatu yang Anda hubungkan ke jarak jauh yang mungkin berada di tengah-tengah test suite yang saling bertentangan). Kelemahannya adalah bahwa perubahan pada proc yang disimpan dapat terjadi dalam produksi tanpa tes yang mencerminkan perubahan, jadi Anda harus disiplin tentang memastikan perubahan itu pertama kali dilakukan dalam lingkungan pengujian.
Pertimbangkan untuk meningkatkan ke ORM. ORM dengan penyedia Linq (hampir semua yang umum digunakan memilikinya) akan memungkinkan Anda untuk mendefinisikan kueri sebagai pernyataan Linq; pernyataan itu kemudian dapat diberikan ke Repositori yang diolok-olok yang memiliki kumpulan data uji dalam memori untuk digunakan. Dengan demikian Anda dapat memverifikasi kueri dengan benar tanpa menyentuh DB (Anda masih harus menjalankan kueri di lingkungan integrasi, untuk menguji bahwa penyedia Linq dapat dengan benar mencerna kueri).
sumber
Saran saya adalah membagi dan menaklukkan . Lupakan database dan kegigihan untuk saat ini dan berkonsentrasilah pada pengujian implementasi palsu dari repositori atau objek akses data Anda.
Saya akan mengejek repositori yang mengembalikan pesanan pembelian. Buat tiruan dengan dua puluh pesanan pembelian aneh.
Stub panggilan ke GetValidPOs sehingga panggilan tiruan Anda, bukan prosedur database.
Anda memerlukan unit-test untuk memastikan data yang benar dikembalikan dari tiruan.
Anda juga memerlukan tes integrasi untuk memastikan data yang benar dikembalikan dari database. Tes integrasi akan memerlukan beberapa konfigurasi dan pembersihan. Misalnya, sebelum menjalankan tes integrasi, seed database Anda dengan menjalankan skrip. Verifikasi bahwa skrip Anda telah berfungsi. Permintaan database dengan memanggil prosedur tersimpan Anda. Pastikan hasil Anda benar. Bersihkan database.
Seperti yang sudah saya katakan, Anda membutuhkan tiruan yang mengembalikan setidaknya beberapa data yang dapat Anda query.
Saat Anda meminta data, Anda ingin memastikan bahwa sistem Anda dapat menangani pengecualian dengan baik. Karenanya, Anda mengejek perilaku sehingga melempar pengecualian dalam skenario tertentu. Anda kemudian menulis tes untuk memastikan bahwa sistem Anda dapat menangani pengecualian ini dengan anggun.
sumber
Seperti halnya pengujian unit Java atau Javascript berarti menulis pengujian unit menggunakan bahasa Java untuk java, dan pengujian unit fungsi Javascript dengan Javascript, menulis tes otomatis untuk mengarahkan Anda menulis prosedur tersimpan berarti perpustakaan tes unit yang Anda cari didasarkan pada penyimpanan Prosedur.
Dengan kata lain, gunakan prosedur tersimpan untuk menguji prosedur tersimpan karena:
Sama seperti TDD dalam bahasa OO, Anda ingin pengujian unit Anda hanya mengatur satu atau dua baris data untuk menguji apa yang diperlukan untuk prosedur (minimalisme, hanya memiliki apa yang dibutuhkan tes sederhana Anda). Hasil dari ini adalah Anda akan memiliki beberapa tes unit sederhana untuk setiap prosedur tersimpan. Tes sederhana ini akan lebih mudah dipertahankan daripada memiliki tes rumit yang bergantung pada set data besar yang tidak mudah memetakan kembali apa yang sebenarnya dibutuhkan tes.
sumber