اختبار Go من الصفر: دليل للمطور المبتدئ

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

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

ابدأ الدورة

لماذا الاختبار في Go ليس مخيفًا، بل ضروري

\n\n

عندما تكتب بلغة Go لأول مرة، يبدو أن المترجم يلتقط كل شيء تقريبًا: الأنواع صارمة، الأخطاء واضحة، nil تحت السيطرة. ولكن بمجرد أن ينمو مشروعك إلى أكثر من 500 سطر، ستدرك: لا يمكنك العيش بدون اختبارات. تعديل واحد في مكان يكسر شيئًا آخر، وتكتشف ذلك فقط في بيئة الإنتاج.

\n\n

في هذه المقالة، سأوضح لك من أين تبدأ اختبار Go كمطور مبتدئ. سنتعرف على اختبارات الوحدة، الاختبارات الجدولية، الكائنات الوهمية (Mocks) وتغطية الكود. لا ماء - فقط أمثلة عملية ونصائح عملية.

\n\n

إذا كنت تكتب بلغة Go لمدة شهرين على الأقل، ستوفر لك هذه المادة ساعات من التصحيح.

\n\n

ما تحتاج معرفته قبل البدء

\n\n

توفر Go حزمة مدمجة testing - لا حاجة لتثبيت أي شيء إضافي. تُكتب الاختبارات في ملفات باللاحقة _test.go وتُشغل بالأمر:

\n\n
go test ./...
\n\n

القواعد الأساسية:

\n
    \n
  • يجب أن تسمى دالة الاختبار TestXxx(t *testing.T)، حيث Xxx هو اسم الدالة المختبرة بحرف كبير.
  • \n
  • ملفات الاختبارات تكون بجانب الكود المختبر.
  • \n
  • يتم الإبلاغ عن الأخطاء عبر t.Error() أو t.Fatal().
  • \n
\n\n

دعنا ننتقل فورًا إلى التطبيق العملي.

\n\n

كتابة أول اختبار وحدة في Go

\n\n

لنفترض أن لدينا دالة بسيطة تجمع رقمين:

\n\n
// calc.go\npackage calc\n\nfunc Sum(a, b int) int {\n    return a + b\n}
\n\n

ننشئ ملف calc_test.go في نفس المجلد:

\n\n
// calc_test.go\npackage calc\n\nimport "testing"\n\nfunc TestSum(t *testing.T) {\n    result := Sum(2, 3)\n    expected := 5\n\n    if result != expected {\n        t.Errorf("Sum(2,3) = %d; want %d", result, expected)\n    }\n}
\n\n

نشغل الاختبار:

\n\n
go test -v
\n\n

سترى PASS باللون الأخضر - أول انتصار اختباري لك. لاحظ: نستخدم t.Errorf (غير قاتل) - سيستمر الاختبار حتى لو فشلت حالة واحدة.

\n\n

الاختبارات الجدولية: عندما يكون اختبار واحد غير مريح

\n\n

تخيل أنك بحاجة لاختبار دالة بعشرات من المدخلات المختلفة. هل تكتب 10 اختبارات منفصلة؟ لا، في Go لهذا الغرض يوجد الاختبارات الجدولية (table-driven tests). هذا هو المعيار في مجتمع Go.

\n\n

نضيف إلى ملف calc.go دالة القسمة:

\n\n
func Divide(a, b int) (int, error) {\n    if b == 0 {\n        return 0, errors.New("division by zero")\n    }\n    return a / b, nil\n}
\n\n

الآن نكتب اختبارًا جدوليًا:

\n\n
func TestDivide(t *testing.T) {\n    tests := []struct {\n        name     string\n        a, b     int\n        expected int\n        wantErr  bool\n    }{\n        {"positive", 10, 2, 5, false},\n        {"negative", -6, 3, -2, false},\n        {"zero division", 5, 0, 0, true},\n        {"same numbers", 7, 7, 1, false},\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            got, err := Divide(tt.a, tt.b)\n            if tt.wantErr {\n                if err == nil {\n                    t.Error("expected error, got nil")\n                }\n                return\n            }\n            if err != nil {\n                t.Errorf("unexpected error: %v", err)\n            }\n            if got != tt.expected {\n                t.Errorf("Divide(%d,%d) = %d; want %d", tt.a, tt.b, got, tt.expected)\n            }\n        })\n    }\n}
\n\n

ما الرائع هنا:

\n
    \n
  • كل حالة هي اختبار فرعي باسم. إذا فشلت واحدة، سيتم تنفيذ البقية.
  • \n
  • سهولة إضافة حالات جديدة - فقط أضف سطرًا إلى الهيكل.
  • \n
  • الكود يُقرأ كمواصفات.
  • \n
\n\n

شغّل مع العلم -v - سترى أسماء جميع الاختبارات الفرعية. هذا مريح جدًا أثناء التصحيح.

\n\n

اختبار

المدونات

توصيات الكتب