
Tes integrasi adalah salah satu level
dari piramida pengujian . Biasanya mereka memerlukan lebih banyak waktu, karena di dalamnya kita tidak mengganti apa pun dengan simulasi komponen nyata. Untuk mengurangi waktu pengujian semacam itu, kita dapat menjalankannya secara paralel. Di sini saya akan secara khusus berbicara tentang tes semacam itu untuk Postgresql.
Idealnya, setiap tes harus independen, sehingga tidak akan saling mempengaruhi. Dengan kata lain, setiap fungsi tes memiliki statusnya sendiri. Ini pertanda baik untuk menggunakan tes paralel. Untuk mendapatkan set data pribadi saya untuk setiap fungsi tes, saya membuat fungsi yang, ketika memulai tes, membuat sirkuit sementara, memuat data ke dalamnya dan menghancurkan sirkuit setelah tes selesai. Setiap
skema yang dibuat berisi hash dalam nama untuk mencegah konflik nama.
Fungsi pembantu
Mari kita mulai dengan
fungsi pembantu untuk menampilkan kesalahan dalam tes. Saya mengambil fungsi pembantu Ben Johnson (Ben Johnson), yang membantu saya menyimpan beberapa baris kode dan membuat kesalahan saya lebih jelas dan terperinci.
Uji data
Untuk menjalankan uji integrasi database, data uji harus disediakan. Alat uji Go memiliki dukungan yang baik untuk memuat data uji dari file. Pertama, pergi buat folder lompatan yang disebut "testdata". Kedua, ketika Anda menjalankan "go test", itu mengubah folder saat ini ke folder paket. Ini memungkinkan Anda untuk menggunakan jalur relatif ke folder testdata untuk memuat kumpulan data uji.
Membuat koneksi database untuk pengujian
package database import ( "math/rand" "strconv" "testing" "time" _ "github.com/lib/pq" "database/sql" ) const ( dbPort = 5439 dbUser = "postgres" dbPassword = "postgres" dbName = "test" ) func CreateTestDatabase(t *testing.T) (*sql.DB, string, func()) { connectionString := fmt.Sprintf("port=%d user=%s password=%s dbname=%s sslmode=disable", dbPort, dbUser, dbPassword, dbName) db, dbErr := sql.Open("postgres", connectionString) if dbErr != nil { t.Fatalf("Fail to create database. %s", dbErr.Error()) } rand.Seed(time.Now().UnixNano()) schemaName := "test" + strconv.FormatInt(rand.Int63(), 10) _, err := db.Exec("CREATE SCHEMA " + schemaName) if err != nil { t.Fatalf("Fail to create schema. %s", err.Error()) } return db, schemaName, func() { _, err := db.Exec("DROP SCHEMA " + schemaName + " CASCADE") if err != nil { t.Fatalf("Fail to drop database. %s", err.Error()) } } }
Memanggil "CreateTestDatabase" untuk membuat koneksi ke database pengujian dan membuat skema data baru untuk pengujian. Fungsi ini mengembalikan koneksi database, nama skema yang dibuat, dan fungsi purge untuk menghapus skema ini. Untuk tes, lebih baik gagal tes daripada mengembalikan kesalahan ke pemanggil. (Catatan: Kembalinya fungsi pembersihan didasarkan pada
Pengujian Lanjutan dengan Bicara dengan Mitchell Hashimoto ).
Unduh Test Dataset
Saya menggunakan file ".sql". Satu (1) sql berisi data untuk satu (1) tabel. Ini termasuk membuat tabel dan mengisinya dengan data. Semua file sql disimpan di folder "testdata". Berikut ini adalah contoh file sql.
CREATE TABLE book ( title character varying(50), author character varying(50) ); INSERT INTO book VALUES ('First Book','First Author'), ('Second Book','Second Author') ;
Dan inilah bagian yang rumit. Karena setiap fungsi berjalan dalam skema data uniknya sendiri, kami tidak bisa hanya menjalankan (menulis) kueri dalam file sql ini. Kita harus menentukan skema sebelum nama tabel untuk membuat tabel atau memasukkan data ke skema sementara yang diinginkan. Misalnya, buku CREATE TABLE ... harus ditulis sebagai CREATE TABLE uniqueschema.book ... dan buku INSERT INTO ... perlu diubah menjadi INSERT INTO uniqueschema.book .... Saya menggunakan ekspresi reguler untuk memodifikasi kueri sebelum mengeksekusi. Berikut adalah kode unduhan data uji:
package datalayer import ( "bufio" "fmt" "io" "os" "regexp" "testing" "database/sql" "github.com/Hendra-Huang/databaseintegrationtest/testingutil"
Uji penciptaan
Sebelum memulai setiap pengujian, database pengujian akan dibuat dengan nama unik untuk skema dan pelaksanaan fungsi pembersihan akan tertunda untuk menghapus skema ini. Nama skema akan dimasukkan ke dalam permintaan dalam ujian. Yang paling penting dalam implementasi ini adalah bahwa koneksi ke database harus dapat disesuaikan untuk mengubah koneksi dari database nyata ke koneksi ke database pengujian. Tambahkan "t.Paralel ()" di awal setiap fungsi tes untuk menunjukkan kepada lingkungan pengujian perlunya menjalankan tes ini secara paralel.
Di bawah ini adalah kode lengkap:
Catatan: Di bawah "TestGetBooks," saya berasumsi bahwa kueri akan mengembalikan 2 buku, sebagai Saya telah memberikan begitu banyak data uji yang diatur dalam "testdata / book.sql" meskipun ada tes masukkan di atas. Jika kami tidak berbagi sirkuit di antara dua tes, "TestGetBooks" akan gagal, karena sekarang 3 baris dalam tabel, 2 dari tes, 1 dari sisipan tes di atas. Ini adalah keuntungan dari rangkaian terpisah untuk pengujian - datanya independen, dan oleh karena itu pengujian independen satu sama lain.Contoh proyek yang saya posting di sini
github . Anda dapat menyalinnya sendiri, menjalankan tes dan melihat hasilnya.
Kesimpulan
Untuk proyek saya, pendekatan ini mengurangi waktu pengujian hingga 40-50%, dibandingkan dengan tes berurutan. Keuntungan lain dari menjalankan tes secara paralel adalah bahwa kita dapat menghindari beberapa kesalahan yang dapat terjadi ketika aplikasi memproses beberapa tindakan kompetitif.
Selamat mencoba.
- Gambar dari
medium.com/kongkow-it-medan/parallel-database-integration-test-on-go-application-8706b150ee2e