الانتقال إلى المحتوى الرئيسي
الوحدة 9 · الدرس 1 من 541/50 في الدورة~12 min
دروس الوحدة (1/5)

حزمة "الاختبار".

في Go، تكون الاختبارات جزءًا من stdlib: لا توجد مكتبة خارجية، ولا يوجد إطار عمل لتكوينه. كل ما تحتاجه هو ملف *_test.go بجوار الرمز، وبعض وظائف TestXxx، والأمر go test.

الاتفاقيات الأساسية

  • تتم تسمية ملفات الاختبار <something>_test.go وهي موجودة في نفس الحزمة مثل الكود الذي تختبره (أو في حزمة <name>_test لـ "اختبارات الصندوق الأسود").
  • تحتوي وظائف الاختبار على توقيع دقيق: func TestXxx(t *testing.T) حيث يبدأ Xxx بحرف كبير.
  • قمت باستيراد testing من ملف stdlib.
  • لا assertEquals: تستخدم if got != want { t.Errorf(...) } مع أفعال fmt.
Go
// math.go
package math

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

// math_test.go
package math

import "testing"

func TestSum(t *testing.T) {
    got := Sum(2, 3)
    if got != 5 {
        t.Errorf("Sum(2,3) = %d; voglio %d", got, 5)
    }
}

تشغيله مع:

Bash
go test ./...        # all packages in the module
go test -v ./pkg     # verbose: prints test names
go test -run TestSum  # only tests matching the regex

t.Error مقابل t.Fatal

هذان هما الفعلان الأساسيان للإشارة إلى الفشل:

الطريقةتأثير
محمي_INLINE_13يتم التسجيل ولكنه لا يفشل (مرئي فقط مع -v أو عند الفشل).
محمي_INLINE_15يسجل ويضع علامة فشل ويستمر في وظيفة الاختبار.
محمي_INLINE_16مثل Error بالتنسيق.
محمي_INLINE_18السجلات، تشير إلى فشل، توقف الاختبار (يستدعي runtime.Goexit).
محمي_INLINE_20مثل Fatal بالتنسيق.

القاعدة الأساسية: استخدم Fatal عندما لا تكون المتابعة منطقية (على سبيل المثال، فشل الإعداد، أو عدم مرجعية مؤشر الصفر الوشيك)؛ بخلاف ذلك Error، والذي يتيح لك رؤية جميع حالات الفشل في عملية تشغيل واحدة.

Go
func TestOpen(t *testing.T) {
    f, err := os.Open("fixtures/sample.txt")
    if err != nil {
        t.Fatal(err) // if it doesn't open, the next steps would fail on nil
    }
    defer f.Close()
    // ... assert on content with t.Errorf
}

الإعداد والتفكيك باستخدام t.Cleanup

لتحرير الموارد في نهاية الاختبار (أو الاختبار الفرعي)، استخدم t.Cleanup بدلاً من defer:

Go
func TestDB(t *testing.T) {
    db := newTestDB(t)
    t.Cleanup(func() { db.Close() })
    // ... test
}

الميزة التي يتميز بها defer: يمكن للمساعد الذي يقوم بإنشاء db تسجيل عملية التنظيف داخليًا، لذلك لا يحتاج المتصلون إلى تذكرها.

مساعدين الاختبار

تقوم الطريقة t.Helper() بوضع علامة على دالة باعتبارها "مساعدة": عندما يفشل الاختبار، فإن تتبع المكدس يتخطى الوظيفة المساعدة ويشير مباشرة إلى المتصل:

Go
func mustParseInt(t *testing.T, s string) int {
    t.Helper()
    n, err := strconv.Atoi(s)
    if err != nil {
        t.Fatalf("parse %q: %v", s, err)
    }
    return n
}

تمارين

تمرين#go.m9.l1.e1
المحاولات: 0جارٍ التحميل…

حدد الدالة TestSum التي تتحقق من Sum(2,3) == 5 باستخدام t.Errorf برسالة منسقة.

جارٍ تحميل المحرر…

الحل متاح بعد 3 من المحاولات

تمرين#go.m9.l1.e2
المحاولات: 0جارٍ التحميل…

في TestDiv، استخدم t.Fatal لإيقاف الاختبار فورًا إذا قام Div بإرجاع قيمة غير متوقعة.

جارٍ تحميل المحرر…

الحل متاح بعد 3 من المحاولات

Quiz#go.m9.l1.e3
جاهز

ما هو الفرق الأساسي بين t.Error وt.Fatal؟

Go
if err != nil {
  t.???(err)
}
خيارات الإجابة