Apakah tes integrasi (database) buruk?

120

Beberapa orang berpendapat bahwa tes integrasi semuanya buruk dan salah - semuanya harus diuji unit, yang berarti Anda harus mengejek dependensi; opsi yang, karena berbagai alasan, saya tidak selalu suka.

Saya menemukan bahwa, dalam beberapa kasus, tes unit tidak membuktikan apa-apa.

Mari kita ambil implementasi repositori (sepele, naif) berikut (dalam PHP) sebagai contoh:

class ProductRepository
{
    private $db;

    public function __construct(ConnectionInterface $db) {
        $this->db = $db;
    }

    public function findByKeyword($keyword) {
        // this might have a query builder, keyword processing, etc. - this is
        // a totally naive example just to illustrate the DB dependency, mkay?

        return $this->db->fetch("SELECT * FROM products p"
            . " WHERE p.name LIKE :keyword", ['keyword' => $keyword]);
    }
}

Katakanlah saya ingin membuktikan dalam pengujian bahwa repositori ini benar-benar dapat menemukan produk yang cocok dengan berbagai kata kunci yang diberikan.

Pendek pengujian integrasi dengan objek koneksi nyata, bagaimana saya bisa tahu bahwa ini sebenarnya menghasilkan permintaan nyata - dan bahwa permintaan itu benar-benar melakukan apa yang saya pikir mereka lakukan?

Jika saya harus mengejek objek koneksi dalam unit-test, saya hanya dapat membuktikan hal-hal seperti "itu menghasilkan permintaan yang diharapkan" - tetapi itu tidak berarti itu benar-benar akan berfungsi ... yaitu, mungkin itu menghasilkan permintaan Saya harapkan, tapi mungkin kueri itu tidak melakukan apa yang saya pikirkan.

Dengan kata lain, saya merasa seperti tes yang membuat pernyataan tentang permintaan yang dihasilkan, pada dasarnya tanpa nilai, karena ini menguji bagaimana findByKeyword()metode itu diterapkan , tetapi itu tidak membuktikan bahwa itu benar-benar berfungsi .

Masalah ini tidak terbatas pada repositori atau integrasi basis data - tampaknya berlaku dalam banyak kasus, di mana membuat pernyataan tentang penggunaan tiruan (uji-ganda) hanya membuktikan bagaimana hal-hal diterapkan, bukan apakah mereka akan sebenarnya bekerja.

Bagaimana Anda menghadapi situasi seperti ini?

Apakah tes integrasi benar-benar "buruk" dalam kasus seperti ini?

Saya mendapatkan poin bahwa lebih baik untuk menguji satu hal, dan saya juga mengerti mengapa pengujian integrasi mengarah ke banyak jalur kode, yang semuanya tidak dapat diuji - tetapi dalam hal layanan (seperti repositori) yang tujuannya hanya untuk untuk berinteraksi dengan komponen lain, bagaimana Anda bisa benar-benar menguji apa pun tanpa pengujian integrasi?

mindplay.dk
sumber
5
Baca agitar.com/downloads/TheWayOfTestivus.pdf , terutama halaman 6 "Tes ini lebih penting daripada unit".
Doc Brown
2
@ user61852 dikatakan "naif" dalam deskripsi, ya?
mindplay.dk
4
Bagaimana rekan kerja Anda benar-benar yakin bahwa database yang diperolokkannya berperilaku sebagai hal yang nyata?
Thorbjørn Ravn Andersen
12
Anda berusaha realistis. Rekan kerja Anda berusaha mematuhi aturan. Selalu tulis tes yang menghasilkan nilai . Jangan buang waktu untuk menulis tes yang tidak dapat dipulihkan, dan jangan menulis tes yang tidak melakukan salah satu dari yang berikut: tingkatkan kemungkinan kode Anda benar atau memaksa Anda untuk menulis kode yang lebih bisa dikelola.
jpmc26
3
@ mindplay.dk: kalimat kunci dalam paragraf itu adalah "Tapi jangan terjebak pada dogma apa pun. Tulis tes yang perlu ditulis." Rekan kerja Anda tampaknya terjebak dalam dogma. Dan Anda tidak membutuhkan seseorang menjelaskan kepada Anda tes apa yang perlu ditulis dalam contoh Anda - Anda sudah tahu itu. Cukup jelas bahwa untuk pengujian jika database Anda memahami kueri, Anda harus menjalankan kueri terhadap database nyata - tidak ada tiruan yang dapat memberi tahu Anda ini
Doc Brown

Jawaban:

129

Rekan kerja Anda benar bahwa segala sesuatu yang dapat diuji unit harus diuji unit, dan Anda benar bahwa tes unit hanya akan membawa Anda sejauh ini dan tidak lebih jauh, terutama ketika menulis pembungkus sederhana di sekitar layanan eksternal yang kompleks.

Cara berpikir yang umum tentang pengujian adalah sebagai piramida pengujian . Ini adalah konsep yang sering dihubungkan dengan Agile, dan banyak yang telah menulis tentangnya, termasuk Martin Fowler (yang menghubungkannya dengan Mike Cohn dalam Succeeding with Agile ), Alistair Scott , dan Google Testing Blog .

        /\                           --------------
       /  \        UI / End-to-End    \          /
      /----\                           \--------/
     /      \     Integration/System    \      /
    /--------\                           \----/
   /          \          Unit             \  /
  --------------                           \/
  Pyramid (good)                   Ice cream cone (bad)

Gagasannya adalah bahwa tes unit yang tangguh dan berjalan cepat adalah dasar dari proses pengujian — harus ada tes unit yang lebih terfokus daripada tes sistem / integrasi, dan lebih banyak tes sistem / integrasi daripada tes ujung ke ujung. Ketika Anda semakin dekat ke atas, tes cenderung mengambil lebih banyak waktu / sumber daya untuk dijalankan, cenderung menjadi lebih rapuh dan keripik, dan kurang spesifik dalam mengidentifikasi sistem atau file yang rusak ; secara alami, lebih baik untuk menghindari "top-heavy".

Untuk itu, tes integrasi tidak buruk , tetapi ketergantungan yang tinggi pada mereka mungkin menunjukkan bahwa Anda belum merancang komponen individual Anda agar mudah diuji. Ingat, tujuannya di sini adalah untuk menguji apakah unit Anda berkinerja terhadap spesifikasinya sambil melibatkan minimum sistem yang dapat pecah lainnya : Anda mungkin ingin mencoba basis data dalam-memori (yang saya hitung sebagai uji coba unit-test-friendly ganda di samping mengolok-olok). ) untuk pengujian kasus tepi berat, misalnya, dan kemudian menulis beberapa tes integrasi dengan mesin database nyata untuk menetapkan bahwa kasing utama bekerja ketika sistem dirakit.


Sebagai catatan, Anda menyebutkan bahwa ejekan yang Anda tulis cukup menguji bagaimana sesuatu diterapkan, bukan apakah itu berfungsi . Itu semacam antipattern: Sebuah tes yang merupakan cermin sempurna dari implementasinya tidak benar-benar menguji apa pun. Sebagai gantinya, uji bahwa setiap kelas atau metode berperilaku sesuai dengan speknya sendiri , pada tingkat abstraksi atau realisme apa pun yang membutuhkan.

Jeff Bowman
sumber
13
+1 untuk "Tes yang merupakan cermin implementasi yang sempurna tidak benar-benar menguji apa pun." Terlalu umum. Saya menyebutnya Doppelganger Antipattern .
dodgethesteamroller
6
Sebuah sekolah pelawan perangkat lunak QA, gerakan pengujian yang didorong oleh konteks , sebagian dikhususkan untuk membantah bahwa ada aturan umum yang berguna seperti Piramida Pengujian. Secara khusus, teks - teks mani gerakan memberikan banyak contoh di mana tes integrasi jauh lebih berharga daripada jenis tes lainnya (karena mereka menguji sistem dalam konteks, sebagai suatu sistem ) ....
dodgethesteamroller
7
... akibatnya, Fowler et al., dalam berargumen bahwa upaya yang lebih sedikit harus dihabiskan untuk tes integrasi dan tes penerimaan pengguna karena mereka terlalu sulit untuk ditulis dengan cara yang kuat dan dapat dipelihara, benar-benar hanya memberikan alasan ex post facto mengapa mereka belum menemukan cara untuk menguji dengan baik di tingkat yang lebih tinggi.
dodgethesteamroller
1
@dodgethesteamroller Diskusi mendalam tentang "sekolah pelawan" seperti itu mungkin paling cocok dengan jawaban mereka sendiri. Secara pribadi, saya menemukan bahwa Google Testing Blog melakukan pekerjaan yang cukup bagus untuk menggambarkan keutamaan dari pengujian otomatis yang cepat dan tertutup bersamaan dengan pengujian sistem-dalam-konteks. Jika Anda menemukan itu tidak jelas, saya daftar piramida tes di sini sebagai model yang berguna atau titik awal, bukan sebagai alasan untuk berhenti berpikir sebagai seorang insinyur.
Jeff Bowman 3-15
1
Presentasi yang sangat direkomendasikan tentang hierarki dan rasio uji integrasi dengan unittests: vimeo.com/80533536 Dijelaskan dengan sangat baik.
szalski
88

Salah satu rekan kerja saya menyatakan bahwa tes integrasi adalah semua jenis yang buruk dan salah - semuanya harus diuji unit,

Itu sedikit seperti mengatakan bahwa antibiotik itu buruk - semuanya harus disembuhkan dengan vitamin.

Tes unit tidak dapat menangkap semuanya - hanya menguji bagaimana komponen bekerja di lingkungan yang terkontrol . Tes integrasi memverifikasi bahwa semuanya bekerja bersama , yang lebih sulit untuk dilakukan tetapi lebih bermakna pada akhirnya.

Proses pengujian yang baik dan komprehensif menggunakan kedua jenis tes - tes unit untuk memverifikasi aturan bisnis dan hal-hal lain yang dapat diuji secara independen, dan tes integrasi untuk memastikan semuanya bekerja bersama.

Pendek pengujian integrasi dengan objek koneksi nyata, bagaimana saya bisa tahu bahwa ini sebenarnya menghasilkan permintaan nyata - dan bahwa permintaan itu benar-benar melakukan apa yang saya pikir mereka lakukan?

Anda dapat mengujinya di tingkat basis data . Jalankan kueri dengan berbagai parameter dan lihat apakah Anda mendapatkan hasil yang Anda harapkan. Memang itu berarti menyalin / menempel perubahan apa pun kembali ke kode "benar". tetapi tidak memungkinkan Anda untuk menguji independen permintaan dari dependensi lainnya.

D Stanley
sumber
Bukankah Anda akan menguji apakah database berisi data tertentu atau tidak?
Tulains Córdova
Mungkin - tetapi Anda juga dapat menguji apakah filter, gabungan kompleks, dll berfungsi. Contoh query mungkin bukan kandidat terbaik untuk "unit test" tetapi satu dengan gabungan kompleks dan / atau agregasi mungkin.
D Stanley
Ya - contoh yang saya gunakan, seperti yang ditunjukkan, sepele; repositori nyata dapat memiliki segala macam opsi pencarian dan penyortiran yang kompleks, misalnya menggunakan pembuat kueri, dll.
mindplay.dk
2
Jawaban yang bagus, tetapi saya akan menambahkan bahwa DB harus ada di memori, untuk memastikan bahwa tes unit cepat.
BЈовић
3
@ BЈовић: Sayangnya, itu mungkin tidak selalu mungkin, karena sayangnya tidak ada dua DB yang kompatibel di luar sana dan tidak semuanya bekerja dalam memori. Ada juga masalah lisensi untuk DB komersial (Anda mungkin tidak memiliki lisensi untuk menjalankannya di mesin apa pun), ...
Matthieu M.
17

Tes unit tidak menangkap semua cacat. Tetapi mereka lebih murah untuk diatur dan dijalankan kembali dibandingkan dengan jenis tes lainnya. Tes unit dibenarkan dengan kombinasi nilai sedang dan biaya rendah hingga sedang.

Berikut adalah tabel yang menunjukkan tingkat deteksi cacat untuk berbagai jenis pengujian.

masukkan deskripsi gambar di sini

sumber: p.470 dalam Kode Lengkap 2 oleh McConnell

Nick Alexeev
sumber
5
Data itu dikumpulkan pada tahun 1986 . Itu tiga puluh tahun yang lalu . Tes unit pada tahun 1986 tidak seperti sekarang ini. Saya akan skeptis dengan data ini. Belum lagi, unit test mendeteksi bug sebelum dilakukan , jadi diragukan bahwa mereka akan dilaporkan.
RubberDuck
3
@RubberDuck Bagan ini dari buku 2006, dan ini didasarkan pada data dari 1986, 1996, 2002 (jika Anda perhatikan dengan teliti). Saya belum melihat ke protokol pengumpulan data di sumber, saya tidak bisa mengatakan kapan mereka mulai melacak cacat dan bagaimana itu dilaporkan. Mungkinkah bagan ini agak ketinggalan zaman? Itu bisa. Desember lalu saya berada di sebuah seminar, dan instruktur menyebutkan bahwa tes integrasi menemukan lebih banyak bug daripada tes unit (dengan faktor 2, iirc). Bagan ini mengatakan bahwa mereka hampir sama.
Nick Alexeev
13

Tidak, itu tidak buruk. Mudah-mudahan, seseorang harus memiliki tes unit dan integrasi. Mereka digunakan dan dijalankan pada berbagai tahap dalam siklus pengembangan.

Tes Unit

Tes unit harus dijalankan pada build server dan secara lokal, setelah kode dikompilasi. Jika ada tes unit gagal, seseorang harus gagal membangun atau tidak melakukan pembaruan kode sampai tes diperbaiki. Alasan mengapa kami ingin unit test diisolasi adalah bahwa kami ingin server build dapat menjalankan semua tes tanpa semua ketergantungan. Kemudian kita bisa menjalankan build tanpa semua dependensi kompleks yang diperlukan dan memiliki banyak tes yang berjalan sangat cepat.

Jadi, untuk database, seseorang harus memiliki sesuatu seperti:

IRespository

List<Product> GetProducts<String Size, String Color);

Sekarang implementasi nyata dari IRepository akan pergi ke database untuk mendapatkan produk, tetapi untuk pengujian unit, seseorang dapat mengejek IRepository dengan yang palsu untuk menjalankan semua tes yang diperlukan tanpa database actaul karena kami dapat mensimulasikan semua jenis daftar produk dikembalikan dari contoh tiruan dan uji logika bisnis apa pun dengan data yang diejek.

Tes Integrasi

Tes integrasi biasanya merupakan tes batas lintas. Kami ingin menjalankan tes ini di server penempatan (lingkungan nyata), kotak pasir, atau bahkan secara lokal (menunjuk ke kotak pasir). Mereka tidak dijalankan di server build. Setelah perangkat lunak digunakan untuk lingkungan, biasanya ini akan dijalankan sebagai aktivitas pasca penempatan. Mereka dapat diotomatisasi melalui utilitas baris perintah. Misalnya, kita bisa menjalankan nUnit dari baris perintah jika kita mengkategorikan semua tes integrasi yang ingin kita panggil. Ini sebenarnya memanggil repositori nyata dengan panggilan database nyata. Jenis tes ini membantu:

  • Kesiapan Stabilitas Kesehatan Lingkungan
  • Menguji hal yang nyata

Tes ini terkadang lebih sulit untuk dijalankan karena kita mungkin perlu mengatur dan / atau merobohkan juga. Pertimbangkan untuk menambahkan produk. Kami mungkin ingin menambahkan produk, menanyakannya untuk melihat apakah sudah ditambahkan, dan kemudian setelah kami selesai, hapus. Kami tidak ingin menambahkan 100 atau 1000 produk "integrasi", jadi diperlukan pengaturan tambahan.

Tes integrasi dapat terbukti sangat berharga untuk memvalidasi lingkungan dan memastikan hal yang sebenarnya berfungsi.

Seseorang harus memiliki keduanya.

  • Jalankan tes unit untuk setiap build.
  • Jalankan tes integrasi untuk setiap penerapan.
Jon Raynor
sumber
Saya akan merekomendasikan menjalankan tes integrasi untuk setiap bangunan, daripada harus melakukan dan mendorong. Tergantung berapa lama waktu yang dibutuhkan, tetapi juga ide yang baik untuk membuatnya cepat karena berbagai alasan.
artbristol
@ ArtBristol - Biasanya server build kami tidak memiliki dependensi lingkungan penuh yang dikonfigurasi, jadi kami tidak dapat menjalankan tes integrasi kami di sana. Tetapi jika seseorang dapat menjalankan tes integrasi di sana, lakukanlah. Kami memiliki kotak pasir penempatan yang disiapkan setelah bangunan yang kami gunakan untuk pengujian integrasi untuk memverifikasi penyebaran. Tetapi setiap situasi berbeda.
Jon Raynor
11

Tes integrasi basis data tidak buruk. Terlebih lagi, mereka perlu.

Anda mungkin memiliki aplikasi Anda dibagi menjadi beberapa lapisan, dan itu adalah hal yang baik. Anda dapat menguji setiap lapisan secara terpisah dengan mengejek lapisan tetangga, dan itu bagus juga. Tetapi tidak peduli berapa banyak lapisan abstraksi yang Anda buat, pada titik tertentu harus ada lapisan yang melakukan pekerjaan kotor - benar-benar berbicara dengan database. Kecuali Anda mengujinya, Anda tidak menguji sama sekali. Jika Anda menguji lapisan n dengan mengolok-olok lapisan n-1, Anda mengevaluasi asumsi bahwa lapisan n berfungsi dengan syarat bahwa lapisan n-1 berfungsi. Agar ini berfungsi, Anda harus membuktikan bahwa layer 0 berfungsi.

Sementara secara teori Anda bisa menyatukan basis data, dengan menguraikan dan menafsirkan SQL yang dihasilkan, jauh lebih mudah dan lebih dapat diandalkan untuk membuat basis data uji dengan cepat dan berbicara dengannya.

Kesimpulan

Apa kepercayaan yang diperoleh dari unit yang menguji Repositori Abstrak Anda , Ethereal Object-Relational-Mapper , Rekaman Aktif Generik , lapisan Ketekunan Teoretik, ketika pada akhirnya SQL Anda yang dihasilkan berisi kesalahan sintaksis?

el.pescado
sumber
Saya berpikir untuk menambahkan balasan yang mirip dengan Anda tetapi Anda telah mengatakannya dengan lebih baik! Dalam pengalaman saya memiliki beberapa tes pada layer yang mendapat dan menyimpan data telah menyelamatkan saya dari banyak kesedihan.
Daniel Hollinrake
Tes integrasi database buruk. Apakah Anda memiliki database yang tersedia di saluran ci / cd Anda? Bagi saya itu agak rumit. Jauh lebih mudah untuk mengejek hal-hal database dan membangun lapisan abstraksi untuk menggunakannya. Tidak hanya itu solusi yang jauh lebih elegan, itu secepat mungkin. Tes unit harus cepat. Menguji basis data Anda akan memperlambat unittests Anda secara signifikan ke tingkat yang tidak dapat diterima. Unittests tidak boleh menghabiskan> 10 menit untuk selesai, bahkan ketika Anda memiliki ribuan dari mereka.
David
@ David Apakah Anda memiliki database yang tersedia di saluran ci / cd Anda? Tentu, itu fitur standar cantik . BTW, saya tidak menganjurkan tes integrasi daripada tes unit - Saya menganjurkan tes integrasi dalam hubungannya dengan tes unit. Tes unit cepat sangat penting, tetapi database terlalu kompleks untuk bergantung pada tes unit dengan interaksi yang diejek.
el.pescado
@ el.pescado saya harus tidak setuju. Jika komunikasi basis data Anda berada di belakang lapisan abstraksi, sangat mudah untuk mengejek. Anda bisa saja memutuskan objek mana yang akan dikembalikan. Juga, fakta bahwa sesuatu itu standar tidak membuatnya menjadi hal yang baik.
David
@ David Saya pikir itu tergantung pada bagaimana Anda mendekati database. Apakah ini detail implementasi atau bagian penting dari sistem ? (Saya condong ke arah yang terakhir) . Jika Anda memperlakukan basis data sebagai penyimpanan data yang bodoh, maka ya, Anda mungkin melakukannya tanpa tes integrasi. Namun, jika ada logika dalam database - kendala, pemicu, kunci asing, transaksi, atau lapisan data Anda menggunakan SQL kustom alih-alih metode ORM biasa, saya merasa unit test saja tidak akan cukup.
el.pescado
6

Anda membutuhkan keduanya.

Dalam contoh Anda jika Anda menguji suatu database dalam kondisi tertentu, ketika findByKeywordmetode ini dijalankan Anda mendapatkan kembali data yang Anda harapkan ini adalah tes integrasi yang bagus.

Dalam kode lain apa pun yang menggunakan findByKeywordmetode itu Anda ingin mengontrol apa yang sedang dimasukkan ke dalam tes, sehingga Anda dapat mengembalikan nol atau kata-kata yang tepat untuk pengujian Anda atau apa pun yang Anda mengejek ketergantungan database sehingga Anda tahu persis apa yang akan diuji oleh Anda menerima (dan Anda kehilangan overhead menghubungkan ke database dan memastikan data di dalamnya benar)

Froome
sumber
6

Penulis artikel blog yang Anda rujuk terutama berkaitan dengan kompleksitas potensial yang dapat timbul dari tes terintegrasi (meskipun ditulis dengan cara yang sangat keras dan kategoris). Namun, tes terintegrasi tidak selalu buruk, dan beberapa sebenarnya lebih bermanfaat daripada tes unit murni. Ini benar-benar tergantung pada konteks aplikasi Anda dan apa yang Anda coba uji.

Banyak aplikasi saat ini tidak akan berfungsi sama sekali jika server database mereka turun. Setidaknya, pikirkan dalam konteks fitur yang Anda coba uji.

Di satu sisi, jika apa yang Anda coba untuk menguji tidak bergantung, atau dapat dibuat tidak bergantung sama sekali, pada database, kemudian tulis tes Anda sedemikian rupa sehingga bahkan tidak mencoba untuk menggunakan database (cukup sediakan data tiruan sesuai kebutuhan). Misalnya, jika Anda mencoba menguji beberapa logika otentikasi saat menyajikan halaman web (misalnya), mungkin merupakan hal yang baik untuk melepaskannya dari DB sama sekali (dengan asumsi Anda tidak bergantung pada DB untuk otentikasi, atau bahwa Anda dapat mengejeknya dengan mudah).

Di sisi lain, jika itu adalah fitur yang secara langsung bergantung pada database Anda dan yang tidak akan bekerja di lingkungan nyata sama sekali jika database tidak tersedia, maka mengejek apa yang dilakukan DB dalam kode klien DB Anda (yaitu layer yang menggunakan DB) tidak selalu masuk akal.

Misalnya, jika Anda tahu bahwa aplikasi Anda akan bergantung pada database (dan mungkin pada sistem database tertentu), mengejek perilaku database demi hal itu sering kali akan membuang-buang waktu. Mesin basis data (terutama RDBMS) adalah sistem yang kompleks. Beberapa baris SQL sebenarnya dapat melakukan banyak pekerjaan, yang akan sulit untuk disimulasikan (pada kenyataannya, jika permintaan SQL Anda adalah beberapa baris panjang, kemungkinan Anda akan membutuhkan lebih banyak baris Java / PHP / C # / Python kode untuk menghasilkan hasil yang sama secara internal): menduplikasi logika yang sudah Anda terapkan dalam DB tidak masuk akal, dan memeriksa bahwa kode pengujian kemudian akan menjadi masalah dengan sendirinya.

Saya tidak perlu memperlakukan ini sebagai masalah unit test vs tes terintegrasi , tetapi melihat ruang lingkup dari apa yang sedang diuji. Masalah keseluruhan pengujian unit dan integrasi tetap ada: Anda memerlukan set data uji dan kasus uji yang cukup realistis, tetapi sesuatu yang juga cukup kecil untuk pengujian dapat dieksekusi dengan cepat.

Waktu untuk mereset basis data dan mengisi kembali dengan data uji merupakan aspek yang perlu dipertimbangkan; Anda biasanya akan mengevaluasi ini terhadap waktu yang diperlukan untuk menulis kode tiruan itu (yang akhirnya harus Anda pertahankan juga).

Hal lain yang perlu dipertimbangkan adalah tingkat ketergantungan aplikasi Anda dengan database.

  • Jika aplikasi Anda cukup mengikuti model CRUD, di mana Anda memiliki lapisan abstraksi yang memungkinkan Anda bertukar antara RDBMS dengan cara sederhana pengaturan konfigurasi, kemungkinan Anda akan dapat bekerja dengan sistem tiruan dengan cukup mudah (mungkin kabur) garis antara unit dan pengujian terintegrasi menggunakan RDBMS dalam memori).
  • Jika aplikasi Anda menggunakan logika yang lebih kompleks, sesuatu yang khusus untuk SQL Server, MySQL, PostgreSQL (misalnya), maka umumnya lebih masuk akal untuk melakukan tes yang menggunakan sistem spesifik itu.
Bruno
sumber
"Banyak aplikasi hari ini tidak akan berfungsi sama sekali jika server database mereka turun" - itu poin yang sangat penting!
el.pescado
Penjelasan bagus tentang batasan tiruan yang rumit, seperti menggunakan bahasa lain untuk mengejek SQL. Ketika kode pengujian menjadi cukup rumit sehingga sepertinya perlu diuji sendiri, itu bau QA.
dodgethesteamroller
1

Anda benar menganggap unit test seperti itu tidak lengkap. Ketidaklengkapan berada dalam antarmuka database yang diejek. Harapan atau pernyataan tiruan naif semacam itu tidak lengkap.

Untuk membuatnya lengkap, Anda harus meluangkan waktu dan sumber daya yang cukup untuk menulis atau mengintegrasikan mesin aturan SQL yang akan menjamin bahwa pernyataan SQL yang dikeluarkan oleh subjek yang diuji, akan menghasilkan operasi yang diharapkan.

Namun, alternatif / pendamping yang sering dilupakan dan agak mahal untuk mengejek adalah "virtualisasi" .

Bisakah Anda memutar contoh DB sementara, dalam-memori tetapi "nyata" untuk menguji satu fungsi? Iya ? di sana, Anda memiliki tes yang lebih baik, yang memeriksa data aktual yang disimpan dan diambil.

Sekarang, bisa dikatakan, Anda mengubah tes unit menjadi tes integrasi. Ada berbagai pandangan tentang di mana harus menarik garis untuk mengklasifikasikan antara tes unit dan tes integrasi. IMHO, "unit" adalah definisi yang sewenang-wenang dan harus sesuai dengan kebutuhan Anda.

SD
sumber
1
ini tampaknya hanya mengulangi poin yang dibuat dan dijelaskan dalam jawaban sebelumnya yang telah diposting beberapa jam yang lalu
Agas
0

Unit Testsdan Integration Testssaling orthgonal . Mereka menawarkan tampilan berbeda pada aplikasi yang Anda buat. Biasanya Anda menginginkan keduanya . Tetapi intinya waktu berbeda, ketika Anda ingin jenis tes.

Yang paling sering Anda inginkan Unit Tests. Tes unit fokus pada sebagian kecil dari kode yang sedang diuji - apa sebenarnya yang disebut a unitdiserahkan kepada pembaca. Tetapi tujuannya sederhana: mendapatkan umpan balik cepat kapan dan di mana kode Anda rusak . Yang mengatakan, harus jelas, bahwa panggilan ke DB yang sebenarnya adalah bukan .

Di sisi lain, ada beberapa hal, yang hanya dapat diuji unit dalam kondisi sulit tanpa database. Mungkin ada kondisi balapan di kode Anda dan panggilan ke DB melempar pelanggaran unique constraintyang hanya bisa dibuang jika Anda benar-benar menggunakan sistem Anda. Tapi tes semacam itu mahal, Anda tidak bisa (dan tidak mau) menjalankannya sesering mungkin unit tests.

Thomas Junk
sumber
0

Di dunia .Net saya memiliki kebiasaan membuat proyek pengujian dan membuat tes sebagai metode pengkodean / debugging / pengujian pulang pergi dikurangi UI. Ini adalah cara yang efisien untuk saya kembangkan. Saya tidak tertarik menjalankan semua tes untuk setiap bangunan (karena itu memperlambat aliran pekerjaan pengembangan saya), tetapi saya memahami manfaatnya untuk tim yang lebih besar. Namun demikian, Anda dapat membuat aturan bahwa sebelum melakukan kode, semua tes harus dijalankan dan lulus (jika diperlukan lebih lama untuk menjalankan tes karena database benar-benar dipukul).

Mengolok-olok lapisan akses data (DAO) dan tidak benar-benar mengenai basis data, tidak hanya tidak memungkinkan saya untuk kode cara saya suka dan sudah terbiasa, tetapi ia melewatkan sebagian besar basis kode yang sebenarnya. Jika Anda tidak benar-benar menguji lapisan akses data dan basis data dan hanya berpura-pura, dan kemudian menghabiskan banyak waktu mengejek, saya gagal memahami manfaat dari pendekatan ini untuk benar-benar menguji kode saya. Saya sedang menguji sepotong kecil bukannya yang lebih besar dengan satu tes. Saya mengerti pendekatan saya mungkin lebih sejalan dengan tes integrasi, tetapi sepertinya tes unit dengan tiruan adalah pemborosan waktu jika Anda benar-benar hanya menulis tes integrasi sekali dan pertama. Ini juga cara yang baik untuk mengembangkan dan men-debug.

Bahkan, untuk sementara waktu sekarang saya telah menyadari TDD dan Bevenor Driven Design (BDD) dan memikirkan cara untuk menggunakannya, tetapi sulit untuk menambahkan tes unit secara surut. Mungkin saya salah, tetapi menulis tes yang mencakup lebih banyak kode ujung ke ujung dengan database yang disertakan, sepertinya tes yang jauh lebih lengkap dan lebih tinggi untuk menulis yang mencakup lebih banyak kode dan merupakan cara yang lebih efisien untuk menulis tes.

Bahkan, saya pikir sesuatu seperti Behavior Driven Design (BDD) yang mencoba menguji ujung ke ujung dengan bahasa spesifik domain (DSL) harus menjadi cara untuk pergi. Kami memiliki SpecFlow di dunia Net, tetapi itu dimulai sebagai sumber terbuka dengan Mentimun.

https://cucumber.io/

Aku hanya benar-benar tidak terkesan dengan kegunaan sebenarnya dari tes yang saya tulis mengejek lapisan akses data dan tidak mengenai database. Objek yang dikembalikan tidak mengenai database dan tidak diisi dengan data. Itu adalah benda yang sepenuhnya kosong yang harus saya tiru dengan cara yang tidak wajar. Saya hanya berpikir itu buang-buang waktu.

Menurut Stack Overflow, mengejek digunakan ketika benda nyata tidak praktis untuk dimasukkan ke dalam unit test.

https://stackoverflow.com/questions/2665812/what-is-mocking

"Mengolok-olok terutama digunakan dalam pengujian unit. Objek yang diuji mungkin memiliki ketergantungan pada objek (kompleks) lainnya. Untuk mengisolasi perilaku objek yang ingin Anda uji, Anda mengganti objek lain dengan mengolok-olok yang mensimulasikan perilaku objek nyata. Ini berguna jika objek nyata tidak praktis untuk dimasukkan ke dalam unit test. "

Argumen saya adalah bahwa jika saya mengkodekan apa saja ujung ke ujung (web UI ke lapisan bisnis ke lapisan akses data ke database, pulang pergi), sebelum saya memeriksa apa pun sebagai pengembang, saya akan menguji aliran perjalanan pulang pergi ini. Jika saya memotong UI dan debug dan menguji aliran ini mulai dari tes, saya menguji semuanya kekurangan UI dan mengembalikan persis apa yang diharapkan UI. Yang tersisa adalah mengirim UI apa yang diinginkan.

Saya memiliki tes yang lebih lengkap yang merupakan bagian dari alur kerja pembangunan alami saya. Bagi saya, itu harus menjadi tes prioritas tertinggi yang mencakup pengujian spesifikasi pengguna aktual ujung ke ujung sebanyak mungkin. Jika saya tidak pernah membuat tes granular lainnya, setidaknya saya memiliki satu tes lebih lengkap yang membuktikan fungsi yang saya inginkan berfungsi.

Salah satu pendiri Stack Exchange tidak yakin tentang manfaat memiliki cakupan uji unit 100%. Saya juga tidak. Saya akan mengambil "tes integrasi" yang lebih lengkap yang mengenai database daripada memelihara sekelompok database mengejek setiap hari.

https://www.joelonsoftware.com/2009/01/31/from-podcast-38/

pengguna3198764
sumber
sangat jelas bahwa Anda tidak mengerti perbedaan antara tes unit dan integrasi
BЈовић
Saya pikir itu tergantung pada proyeknya. Pada proyek yang lebih kecil dengan sumber daya lebih sedikit di mana pengembang lebih bertanggung jawab secara keseluruhan untuk pengujian dan pengujian regresi karena kurangnya penguji dan menjaga dokumentasi selaras dengan kode, jika saya akan menghabiskan waktu menulis tes, itu akan menjadi yang memberi saya bang paling untuk uang saya. Saya ingin membunuh burung sebanyak mungkin dengan satu batu. Jika sebagian besar logika dan bug saya berasal dari prosedur tersimpan basis data yang menghasilkan laporan, atau dari JavaScript ujung depan, memiliki cakupan uji unit lengkap di tingkat menengah tidak banyak membantu.
user3198764
-1

Ketergantungan eksternal harus diejek karena Anda tidak dapat mengontrolnya (mereka mungkin lulus selama fase pengujian integrasi tetapi gagal dalam produksi). Drive bisa gagal, koneksi basis data bisa gagal karena sejumlah alasan, mungkin ada masalah jaringan dll. Memiliki tes integrasi tidak memberikan kepercayaan ekstra karena mereka semua masalah yang bisa terjadi saat runtime.

Dengan tes unit yang sebenarnya, Anda menguji dalam batas-batas kotak pasir dan itu harus jelas. Jika pengembang menulis kueri SQL yang gagal pada QA / PROD itu berarti mereka bahkan tidak mengujinya sekali sebelum waktu itu.

vidalsasoon
sumber
+1 untuk "Anda tidak dapat mengontrol mereka (mereka mungkin lulus selama fase pengujian integrasi tetapi gagal dalam produksi)" .
Tulains Córdova
Anda dapat mengontrolnya hingga tingkat kepuasan.
el.pescado
Saya mengerti maksud Anda, tetapi saya pikir ini dulu lebih benar daripada hari ini? Dengan otomatisasi dan alat-alat (seperti Docker) Anda sebenarnya dapat mereplikasi dan mengulangi pengaturan semua dependensi biner / server Anda secara akurat dan andal untuk suite uji integrasi. Tentu saja, ya, perangkat keras fisik (dan layanan pihak ketiga, dll.) Dapat gagal.
mindplay.dk
5
Saya sama sekali tidak setuju. Anda harus menulis tes integrasi (tambahan) karena dependensi ekstenal dapat gagal. Ketergantungan eksternal mungkin memiliki kebiasaan sendiri, yang kemungkinan besar akan Anda lewatkan ketika Anda mengejek segalanya.
Paul Kertscher 3-15
1
@ PaulK masih memikirkan jawaban mana yang harus diterima, tapi saya condong ke kesimpulan yang sama.
mindplay.dk