عن المشروع

# go-docker-testsuite مكتبة Go لتشغيل التبعيات الخارجية في حاويات Docker لاختبارات التكامل. تتيح لك تشغيل أي صورة Docker—قواعد البيانات، قوائم الانتظار، ذاكرة التخزين المؤقت، أو تخزين الكائنات—والاتصال بها من اختبارات Go الخاصة بك. ## الميزات - **Container** — غلاف منخفض المستوى لإنشاء وتشغيل وانتظار الإخراج وتنظيف أي صورة Docker - **Group** — تشغيل حاويات متعددة في شبكة Docker معزولة مع اتصال على مستوى IP - **Applications** — أغلفة جاهزة للاستخدام للخدمات الشائعة (MySQL، PostgreSQL، Redis، Kafka، إلخ.) - **Hooks** — استدعاءات دورة الحياة (BeforeRun، AfterRun، BeforeClose، AfterClose) لكل حاوية - **Exec** — تشغيل الأوامر داخل حاوية قيد التشغيل والتقاط stdout وstderr ورمز الخروج - **أوامر دورة الحياة** — تشغيل أوامر بدء التشغيل / بعد الجاهزية عبر exec - **نسخ الملفات إلى الحاويات** — إدخال الملفات قبل البدء باستخدام `WithFiles` - **نسخ الملفات من الحاويات** — قراءة الملفات من حاوية قيد التشغيل كتدفق tar - **حدود الموارد** — تحديد وحدة المعالجة المركزية / الذاكرة / العمليات لحماية المضيف وCI - **Matchers** — انتظار سجلات الحاوية مع مطابقات سلسلة فرعية أو دقيقة أو regexp - **استراتيجيات الانتظار** — فحوصات جاهزية قابلة للتركيب (ForLog، ForHTTPGet، ForCommand، ForTCPConnection) - **منشئ البيئة** — DSL سلس للمتغيرات البيئية المكتوبة - **ربط المنافذ** — تعيين منفذ DNAT مع تخصيص عشوائي أو واحد لواحد - **وضع الشبكة** — دعم الشبكة المضيفة أو الشبكة المخصصة - **IMAGE_PREFIX** — توجيه الصور عبر وكيل / مرآة - **ربط `*testing.T`** — إيقاف تشغيل تلقائي وتسجيل مع `t.Parallel()` آمن ## المتطلبات - Go 1.26+ - خادم Docker قيد التشغيل (يعمل مع المضيفين البعيدين عبر `DOCKER_HOST`) ## التثبيت مساحة عمل متعددة الوحدات: الجذر هو الوحدة الأساسية، وكل تطبيق تحت `applications/<name>` هو وحدة Go خاصة به. اسحب ما تحتاجه فقط: ```sh go get github.com/teran/go-docker-testsuite # غلاف تطبيق محدد: go get github.com/teran/go-docker-testsuite/applications/redis go get github.com/teran/go-docker-testsuite/applications/postgres ``` ## التطبيقات أغلفة جاهزة للاستخدام (كل منها يعيد واجهة عميل مكتوبة ويتعامل مع بدء التشغيل وفحوصات الصحة والتنظيف): - Ceph (RGW) مع AWS SDK v2 - ClickHouse مع clickhouse-go - Forgejo مع SQLite - FRR routing suite مع vtysh - K3s مع client-go - Kafka مع Sarama - Memcache مع gomemcache - MinIO (متوافق مع S3) - MongoDB مع mongo-driver - MySQL / MariaDB / Percona Server - NetBox مع PostgreSQL + Redis - Nginx - OpenSearch مع opensearch-go - Paperless-ngx مع PostgreSQL + Valkey - PostgreSQL مع pgx - Prometheus مع prometheus/client_golang - RabbitMQ (AMQP + Management API) - Redis مع go-redis - ScyllaDB مع gocql - Vault - Libvirtd (KVM/QEMU) تتضمن العديد من الحزم أمثلة قابلة للاختبار على pkg.go.dev. ## الاستخدام ### بدء سريع — MySQL ```go package main import ( "context" "database/sql" "time" _ "github.com/go-sql-driver/mysql" "github.com/teran/go-docker-testsuite/applications/mysql" ) func main() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel() app, err := mysql.New(ctx, "index.docker.io/library/mysql:8.0.4") if err != nil { panic(err) } defer app.Close(ctx) if err := app.CreateDB(ctx, "important_database"); err != nil { panic(err) } db, err := sql.Open("mysql", app.MustDSN("important_database")) if err != nil { panic(err) } defer db.Close() if _, err := db.ExecContext(ctx, "SELECT 1"); err != nil { panic(err) } } ``` ### مجموعة متعددة الحاويات ```go package main import ( "context" "time" "github.com/teran/go-docker-testsuite" "github.com/teran/go-docker-testsuite/wait" ) func main() { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel() app := docker.NewApplication( c, docker.HookFunc(func(ctx context.Context, ht docker.HookType, c docker.Container) error { return wait.Wait(ctx, c, wait.ForLog(docker.NewSubstringMatcher("ready"))) }), ) g, err := docker.NewGroup("my-services", app1, app2) if err != nil { panic(err) } if err := g.Run(ctx); err != nil { panic(err) } defer g.Close(ctx) } ``` ### استراتيجيات الانتظار ```go if err := wait.Wait(ctx, c, wait.ForHTTPGet(8080, wait.WithPath("/health"), wait.WithResponseStatuses(200), )); err != nil { panic(err) } ``` استراتيجيات أخرى: `ForLog`، `ForCommand`، `ForTCPConnection`. ادمجها مع `ForAll` / `ForAny` / `ForAtLeast`. ### ربط `*testing.T` ```go func TestRedis(t *testing.T) { t.Parallel() c, err := docker.NewContainerWithT( t, "redis", images.Redis, nil, docker.NewEnvironment(), docker.NewPortBindings().PortDNAT(docker.ProtoTCP, 6379), ) if err != nil { t.Fatal(err) } c.RunT(ctx) // fail-fast; يسجل t.Cleanup } ``` ### خطافات دورة الحياة ```go docker.HookTypeBeforeRun // قبل بدء الحاوية docker.HookTypeAfterRun // بعد بدء الحاوية docker.HookTypeBeforeClose // قبل إيقاف الحاوية docker.HookTypeAfterClose // بعد إيقاف الحاوية ``` ### Exec وأوامر دورة الحياة ```go res, err := c.Exec(ctx, []string{"echo", "hello"}) if err != nil { panic(err) } if err := res.Error(); err != nil { panic(err) } fmt.Printf("رمز الخروج: %d\n", res.ExitCode) fmt.Printf("stdout: %s", res.Stdout) ``` ### نسخ الملفات إلى / من الحاويات استخدم `WithFiles` مع `FileFromBytes` للمحتوى الصغير أو `io.Reader` + `Size` للملفات الكبيرة. اقرأ الملفات مرة أخرى باستخدام `docker.CopyFromContainer`. ### بادئة الصورة / الوكيل ```sh export IMAGE_PREFIX=registry-mirror.example.com ``` ## الوحدات والإصدارات مساحة عمل متعددة الوحدات برقم إصدار واحد، موسومة بشكل منفصل (مثل، الأساسي `v1.6.0`، التطبيق `applications/redis/v1.6.0`). ترتيب الإصدار: الأساسي أولاً، ثم التطبيقات. استخدم Makefile للوسم. ## الترخيص رخصة Apache، الإصدار 2.0