Dalam proyek saya saat ini, saya mengalami kesulitan menghasilkan solusi yang baik untuk membuat tes integrasi scalable yang tidak memiliki efek samping. Klarifikasi kecil tentang efek samping properti bebas: sebagian besar tentang database; seharusnya tidak ada perubahan dalam database setelah tes selesai (status harus dipertahankan). Mungkin skalabilitas dan pelestarian negara tidak datang bersamaan, tetapi saya benar-benar ingin mendorong solusi yang lebih baik.
Berikut ini adalah tes integrasi khas (tes ini menyentuh lapisan basis data):
public class OrderTests {
List<Order> ordersToDelete = new ArrayList<Order>();
public testOrderCreation() {
Order order = new Order();
assertTrue(order.save());
orderToDelete.add(order);
}
public testOrderComparison() {
Order order = new Order();
Order order2 = new Order();
assertFalse(order.isEqual(order2);
orderToDelete.add(order);
orderToDelete.add(order2);
}
// More tests
public teardown() {
for(Order order : ordersToDelete)
order.delete();
}
}
Seperti yang bisa dibayangkan, pendekatan ini menghasilkan tes yang sangat lambat. Dan, ketika diterapkan pada keseluruhan tes integrasi, dibutuhkan sekitar 5 detik untuk menguji hanya sebagian kecil dari sistem. Saya bisa membayangkan angka ini naik ketika cakupan ditingkatkan.
Apa yang akan menjadi pendekatan lain untuk menulis tes seperti itu? Salah satu alternatif yang dapat saya pikirkan adalah memiliki jenis variabel global (dalam kelas) dan semua metode pengujian berbagi variabel ini. Akibatnya, hanya sedikit pesanan yang dibuat & dihapus; menghasilkan tes yang lebih cepat. Namun, saya pikir ini menimbulkan masalah yang lebih besar; tes tidak lagi terisolasi dan semakin sulit untuk memahami & menganalisisnya.
Mungkin saja tes integrasi tidak dimaksudkan untuk dijalankan sesering tes unit; karena itu kinerja rendah mungkin dapat diterima oleh mereka. Dalam kasus apa pun, akan lebih baik untuk mengetahui apakah seseorang datang dengan alternatif untuk meningkatkan skalabilitas.
Ini adalah masalah abadi yang dihadapi semua orang saat menulis tes integrasi.
Solusi ideal, terutama jika Anda menguji pada produksi, membuka transaksi di setup dan menggulungnya kembali di teardown. Saya pikir ini harus sesuai dengan kebutuhan Anda.
Di mana itu tidak mungkin, misalnya di mana Anda menguji aplikasi dari lapisan klien, solusi lain adalah menggunakan DB pada mesin virtual dan mengambil snapshot dalam pengaturan dan kembali ke sana di teardown (itu tidak butuh waktu selama yang Anda harapkan).
sumber
Tes integrasi harus selalu dijalankan terhadap pengaturan produksi. Dalam kasus Anda itu berarti Anda harus memiliki database dan server aplikasi yang sama. Tentu saja, demi kinerja, Anda dapat memutuskan untuk menggunakan DB dalam memori.
Apa yang tidak boleh Anda lakukan adalah memperluas ruang lingkup transaksi Anda. Beberapa orang menyarankan untuk mengambil alih kendali atas transaksi dan mengembalikannya setelah pengujian. Ketika Anda melakukan ini, semua entitas (dengan asumsi Anda menggunakan JPA) akan tetap melekat pada konteks kegigihan selama pelaksanaan tes. Ini dapat menyebabkan beberapa bug yang sangat jahat yang sangat sulit ditemukan .
Sebagai gantinya, Anda harus menghapus database secara manual setelah setiap tes melalui perpustakaan seperti JPAUnit atau mirip dengan pendekatan ini (hapus semua tabel menggunakan JDBC).
Pada masalah kinerja Anda, Anda tidak boleh melakukan tes integrasi pada setiap build. Biarkan server integrasi berkelanjutan Anda melakukan ini. Jika Anda menggunakan Maven, Anda mungkin menikmati failsafe plug-in yang memungkinkan Anda untuk memisahkan tes Anda ke dalam unit dan integrasi tes.
Juga, Anda tidak seharusnya mengejek apa pun. Ingat Anda pengujian integrasi, yaitu perilaku pengujian di dalam lingkungan eksekusi run-time.
sumber
Tentang skalabilitas
Saya pernah mengalami masalah ini beberapa kali sebelumnya, bahwa tes integrasi terlalu lama untuk dijalankan dan tidak praktis bagi satu pengembang untuk terus berjalan dalam umpan balik perubahan yang ketat. Beberapa strategi untuk mengatasi ini adalah:
Coba gabungkan teknik-teknik ini untuk efek yang lebih besar.
sumber
Untuk tujuan pengujian kami telah menggunakan penyebaran berbasis file dari database SQLite (cukup salin sumber daya). Ini dilakukan agar kami juga dapat menguji migrasi skema. Sejauh yang saya ketahui, perubahan skema tidak bersifat transaksional sehingga tidak akan dibatalkan setelah transaksi dibatalkan. Juga tidak harus bergantung pada dukungan transaksi untuk pengaturan pengujian memungkinkan untuk menguji perilaku transaksi dari aplikasi Anda dengan benar.
sumber