اختبار التكامل في Go باستخدام Docker: دليل شامل
اختبار التكامل هو مرحلة أساسية في تطوير تطبيقات Go الموثوقة. على عكس اختبارات الوحدة، تتحقق اختبارات التكامل من تفاعل المكونات: قاعدة البيانات، ذاكرة التخزين المؤقت، واجهات برمجة التطبيقات الخارجية. يتيح Docker عزل بيئة الاختبار، مما يجعل الاختبارات قابلة للتكرار ومستقلة عن الجهاز المضيف. في هذه المقالة، سنشرح كيفية إعداد اختبار التكامل لتطبيقات Go باستخدام Docker — من الحاويات البسيطة إلى السيناريوهات المتقدمة مع Testcontainers و CI/CD.
1. لماذا Docker لاختبار التكامل في Go؟
غالبًا ما تعمل تطبيقات Go مع PostgreSQL أو Redis أو MongoDB أو خدمات أخرى. الإعداد اليدوي لهذه التبعيات على كل جهاز مطور وخادم CI هو طريق للأخطاء. يحل Docker هذه المشكلة:
- قابلية التكرار — نفس البيئة محليًا وفي CI.
- العزل — الاختبارات لا تلوث النظام المضيف.
- السرعة — يتم تشغيل الحاويات في ثوانٍ.
- التوازي — يمكن تشغيل عدة اختبارات معزولة في وقت واحد.
لننظر إلى مثال أساسي: اختبار دالة تحفظ البيانات في PostgreSQL.
2. إعداد بيئة الاختبار باستخدام Docker Compose
لننشئ docker-compose.test.yml لقاعدة بيانات الاختبار:
version: '3.8'services: postgres_test: image: postgres:16-alpine environment: POSTGRES_USER: test POSTGRES_PASSWORD: test POSTGRES_DB: testdb ports: - "5433:5432" # نستخدم منفذًا غير قياسي لتجنب التعارض مع قاعدة البيانات المحلية tmpfs: /var/lib/postgresql/data # البيانات في الذاكرة للسرعةفي اختبار Go، نرفع الحاوية عبر os/exec أو نستخدم مكتبة testcontainers-go. سنعرض كلا النهجين.
2.1. تشغيل Docker Compose يدويًا من الاختبار
// main_test.gopackage main
import ( "context" "fmt" "os/exec" "testing" "time")
func setupTestDB(t *testing.T) string { t.Helper() // تشغيل الحاوية cmd := exec.Command("docker-compose", "-f", "docker-compose.test.yml", "up", "-d") if err := cmd.Run(); err != nil { t.Fatalf("فشل تشغيل docker-compose: %v", err) } // انتظار جاهزية PostgreSQL time.Sleep(3 * time.Second) return "postgres://test:test@localhost:5433/testdb?sslmode=disable"}
func TestSaveUser(t *testing.T) { dsn := setupTestDB(t) db, err := sql.Open("postgres", dsn) if err != nil { t.Fatal(err) } defer db.Close() // ... كود الاختبار}العيوب: sleep يدوي، صعوبة مع الاختبارات المتوازية. من الأفضل استخدام Testcontainers.
2.2. Testcontainers لـ Go
قم بتثبيت المكتبة:
go get github.com/testcontainers/testcontainers-goمثال مع إدارة تلقائية للحاوية:
// repository_test.gopackage repository
import ( "context" "testing" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" "github.com/jackc/pgx/v5/pgxpool")
func TestUserRepository_Save(t *testing.T) { ctx := context.Background()
// طلب حاوية PostgreSQL req := testcontainers.ContainerRequest{ Image: "postgres:16-alpine", ExposedPorts: []string{"5432/tcp"}, Env: map[string]string{ "POSTGRES_USER": "test", "POSTGRES_PASSWORD": "test", "POSTGRES_DB": "testdb", }, WaitingFor: wait.ForLog("database system is ready to accept connections"), }
postgres, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req