Bagaimana cara membuat tes integrasi gratis yang dapat diukur & efek samping?

14

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.

Guven
sumber

Jawaban:

6

Lihat menggunakan Hypersonic, atau DB dalam memori lainnya untuk pengujian unit. Tes tidak hanya akan mengeksekusi lebih cepat, tetapi efek samping tidak relevan. (Mengembalikan transaksi setelah setiap tes juga memungkinkan untuk menjalankan banyak tes pada contoh yang sama)

Ini juga akan memaksa Anda untuk membuat mockup data, yang merupakan hal yang baik IMO, karena itu berarti sesuatu yang terjadi pada basis data produksi tidak dapat dijelaskan mulai gagal dalam pengujian Anda, DAN itu memberi Anda titik awal untuk apa "instalasi database bersih" "Akan terlihat seperti, yang membantu jika Anda perlu tiba-tiba menyebarkan contoh aplikasi baru tanpa koneksi ke situs produksi yang ada.

Ya, saya menggunakan metode ini sendiri, dan ya itu adalah PITA untuk mengatur waktu PERTAMA, tetapi lebih dari itu dibayarkan untuk dirinya sendiri dalam masa proyek yang akan saya selesaikan. Ada juga sejumlah alat yang membantu dengan maket data.

SplinterReality
sumber
Kedengarannya seperti ide bagus. Saya terutama menyukai aspek isolasi lengkap itu; dimulai dengan instalasi basis data baru. Tampaknya butuh usaha, tetapi begitu pengaturan, itu akan sangat bermanfaat. Terima kasih.
Guven
3

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).

pdr
sumber
Saya tidak percaya saya belum memikirkan pengembalian transaksi. Saya akan menggunakan ide itu sebagai solusi cepat untuk solusi, tetapi pada akhirnya DB di dalam memori terdengar sangat menjanjikan.
Guven
3

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.

BenR
sumber
Jawaban yang bagus. Satu poin: Mungkin dapat diterima untuk mengejek beberapa dependensi eksternal (mis. Mengirim email). Tetapi Anda harus lebih mengejek dengan menyiapkan layanan / server tiruan lengkap, bukan mengejeknya dalam kode Java.
sleske
Sleske, saya setuju dengan Anda. Terutama ketika Anda menggunakan JPA, EJB, JMS atau menerapkan terhadap spesifikasi lain. Anda dapat menukar server aplikasi, penyedia ketekunan, atau database. Misalnya, Anda mungkin ingin menggunakan Glassfish dan HSQLDB tertanam untuk hanya mengatur dan meningkatkan kecepatan (Anda tentu saja bebas memilih implementasi tersertifikasi lainnya).
BenR
2

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:

  • Tulis lebih sedikit tes integrasi - jika Anda memiliki jangkauan yang baik dengan tes unit dalam sistem, tes integrasi harus lebih fokus pada masalah integrasi (ahem), tentang bagaimana komponen yang berbeda bekerja bersama. Mereka lebih mirip dengan tes asap, yang hanya mencoba untuk melihat apakah sistem masih berfungsi secara keseluruhan. Jadi, idealnya, tes unit Anda mencakup sebagian besar bagian fungsional aplikasi, dan tes integrasi hanya memeriksa bagaimana bagian-bagian tersebut berinteraksi satu sama lain. Anda tidak perlu jangkauan luas jalur logis di sini, hanya beberapa jalur kritis melalui sistem.
  • Jalankan hanya sebagian himpunan tes pada satu waktu - sebagai pengembang tunggal yang mengerjakan beberapa fungsi, Anda biasanya memiliki perasaan untuk menguji yang diperlukan untuk mencakup fungsionalitas itu. Jalankan hanya tes yang masuk akal untuk menutupi perubahan Anda. Kerangka kerja seperti JUnit memungkinkan Anda untuk mengelompokkan perlengkapan dalam suatu kategori . Buat pengelompokan yang memungkinkan cakupan terbaik untuk setiap fitur yang Anda miliki. Tentu saja, Anda masih ingin menjalankan semua tes integrasi di beberapa titik, mungkin sebelum melakukan ke sistem kontrol sumber dan tentu saja di server integrasi berkelanjutan.
  • Optimalkan sistem - Tes integrasi ditambah dengan beberapa tes kinerja mungkin memberi Anda input yang diperlukan untuk menyempurnakan bagian sistem yang lambat, sehingga pengujian akan berjalan lebih cepat nanti. Ini mungkin membantu mengungkap indeks yang diperlukan dalam database, antarmuka yang akrab antara subsistem atau hambatan kinerja lainnya yang perlu diatasi.
  • Jalankan tes Anda secara paralel - Jika Anda memiliki pengelompokan tes orthogonal yang baik, Anda dapat mencoba menjalankannya secara paralel . Berhati-hatilah dengan persyaratan ortogonal yang saya sebutkan, Anda tidak ingin ujian Anda saling bertentangan.

Coba gabungkan teknik-teknik ini untuk efek yang lebih besar.

Jordão
sumber
1
Pedoman yang sangat bagus; menulis lebih sedikit tes integrasi pasti adalah saran terbaik. Juga, menjalankannya secara paralel akan menjadi alternatif yang sangat baik; "tes" sempurna untuk memeriksa apakah saya mendapatkan tes saya lurus dalam hal isolasi.
Guven
2

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.

Carlo Kuip
sumber