اختبارات Go: Unit، Integration، E2E — دليل شامل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة
```html

الاختبار في Go: Unit، Integration، E2E — دليل شامل



الاختبار هو جزء لا يتجزأ من تطوير البرمجيات عالية الجودة. في لغة Go (Golang)، تم تضمين الاختبار على مستوى المكتبة القياسية، مما يجعله بسيطًا وفعالًا. في هذه المقالة، سنقوم بتحليل المستويات الثلاثة الرئيسية للاختبار: اختبارات الوحدة (unit)، واختبارات التكامل (integration)، والاختبارات الشاملة (e2e). ستتعلم كيفية كتابتها، ومتى تستخدمها، وما هي الأدوات التي يجب استخدامها.



لماذا يعتبر الاختبار في Go مهمًا جدًا؟



تم إنشاء Go مع التركيز على البساطة والموثوقية. تتيح الحزمة المدمجة testing وأداة go test إضافة الاختبارات بسهولة إلى أي مشروع. تلتزم فريق Go بفلسفة: "إذا لم يتم اختبار الكود، فهو لا يعمل". يساعد الاختبار في:



  • اكتشاف الأخطاء في المراحل المبكرة من التطوير
  • تبسيط إعادة هيكلة الكود وصيانته
  • توثيق سلوك الدوال والوحدات
  • زيادة الثقة في استقرار التطبيق


اختبار الوحدة (Unit Testing) في Go



تتحقق اختبارات الوحدة (unit tests) من عمل الدوال أو الطرق أو الهياكل الفردية بشكل منفصل عن التبعيات الخارجية. في Go، تُكتب في ملفات ذات اللاحقة _test.go.



أساسيات اختبارات الوحدة



لننظر إلى مثال بسيط. لنفترض أن لدينا دالة جمع:



// math.gopackage main

func Add(a, b int) int { return a + b}


سيبدو اختبار هذه الدالة كالتالي:



// math_test.gopackage main

import "testing"

func TestAdd(t *testing.T) { result := Add(2, 3) expected := 5 if result != expected { t.Errorf("Add(2, 3) = %d; want %d", result, expected) }}


تشغيل الاختبار: go test -v



الاختبارات الجدولية (Table-driven tests)



يشجع Go على استخدام الاختبارات الجدولية للتحقق من سيناريوهات متعددة:



func TestAddTableDriven(t *testing.T) {    tests := []struct {        name string        a, b int        want int    }{        {"positive numbers", 2, 3, 5},        {"negative numbers", -1, -2, -3},        {"zero", 0, 0, 0},        {"mixed", -5, 10, 5},    }

for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := Add(tt.a, tt.b) if got != tt.want { t.Errorf("Add(%d, %d) = %d; want %d", tt.a, tt.b, got, tt.want) } }) }}


الاختبار باستخدام الكائنات الوهمية (Mock)



لعزل اختبارات الوحدة، غالبًا ما تكون هناك حاجة إلى كائنات وهمية (mocks). في Go، يمكن استخدام الواجهات (interfaces) والمكتبات مثل gomock أو testify/mock.



// تعريف الواجهةtype UserRepository interface {    GetUser(id int) (User, error)}

// اختبار باستخدام testifyfunc TestGetUserName(t *testing.T) { mockRepo := new(MockUserRepository) mockRepo.On("GetUser", 1).Return(User{Name: "Alice"}, nil)

service := NewUserService(mockRepo) name, err := service.GetUserName(1)

assert.NoError(t, err) assert.Equal(t, "Alice", name) mockRepo.AssertExpectations(t)}


اختبار التكامل (Integration Testing) في Go



تتحقق اختبارات التكامل من التفاعل بين مكونات النظام: قواعد البيانات، واجهات برمجة التطبيقات (APIs)، أنظمة الملفات، والخدمات الخارجية الأخرى. في Go، من الشائع وضعها في حزم منفصلة أو استخدام build tags.



الاختبار مع قاعدة البيانات



لاختبار العمل مع قاعدة البيانات، غالبًا ما يتم استخدام testcontainers أو قواعد بيانات مؤقتة:



// integration_test.go (مع build tag)//go:build integration

package integration

import ( "database/sql" "testing" _ "github.com/lib/pq")

func TestUserRepository(t *testing.T) { // الاتصال بقاعدة بيانات الاختبار db, err := sql.Open("postgres", "host=localhost port= ```

المدونات

توصيات الكتب