مقدمة: السؤال الأبدي "كيف يمكنني إخراج شيء ما في الاختبار؟"
\n\nأنت تكتب اختبارًا بلغة Go. المنطق معقد، والبيانات متشابكة، وتحتاج بشدة لرؤية ما يحدث في الداخل. تكتب تلقائيًا fmt.Println("value =", x)، وتشغل الاختبار... وترى صمتًا تامًا. لا يوجد أي إخراج. هل هذا مألوف؟
هذا السؤال هو أحد أكثر الأسئلة شيوعًا على Stack Overflow بين مطوري Go المبتدئين (وليس فقط!). قد يبدو الأمر بسيطًا، وهو إخراج سطر نصي؟ لكن في عالم اختبار Go، هناك قواعد خاصة ومجموعة أدوات مهذبة. في هذه المقالة، سنستعرض جميع طرق الإخراج في الاختبارات، ونصنفها حسب أفضل الممارسات لعام 2025، ونوضح كيف تتجنب الأخطاء. هيا بنا!
\n\nلماذا fmt.Println صامت؟ (ومتى يتحدث أخيرًا؟)
\n\nدعنا نصل إلى صلب الموضوع فورًا. عندما تشغل الاختبارات باستخدام الأمر go test (بدون علامات)، يتم كبت الإخراج القياسي (stdout). يعتبر مُختبر Go أنه إذا نجح الاختبار، فلا يحتاج المستخدم إلى رؤية أطنان من معلومات التصحيح. تم ذلك من أجل النظافة والأتمتة - تخيل لو أن كل اختبار يخرج 10 أسطر من السجل في كل مرة تشغل فيها CI/CD.
ومع ذلك، هناك استثناءان حيث سيظهر fmt.Println على الشاشة:
- \n
- العلامة
-v(مفصلة):go test -v. هذا الوضع يتيح إخراجًا مفصلاً لجميع الاختبارات. سترى رسائل منfmt.Printlnوالوظائف الأخرى. \n - فشل الاختبار: إذا انتهى الاختبار بخطأ (باستدعاء
t.Errorأوt.Fatal)، فسيتم عرض إخراجfmt.Printlnمن هذا الاختبار. هذا مفيد جدًا للتصحيح. \n
لكن الاعتماد على fmt.Println هو أمر غير لائق. للاختبارات في Go، هناك أداة خاصة، أكثر صحة وقوة.
ملك الحفلة: t.Log() و t.Logf()
\n\nكائن testing.T (الذي يُمرر إلى كل اختبار) يحتوي على طرق مدمجة لتسجيل السجلات. احفظها كـ "أبانا": t.Log() و t.Logf().
package main\n\nimport (\n "testing"\n)\n\nfunc TestSum(t *testing.T) {\n result := 2 + 2\n // تسجيل بسيط\n t.Log("نبدأ اختبار المجموع")\n t.Log("نتيجة الحساب:", result)\n\n // تسجيل مع تنسيق (مثل fmt.Printf)\n t.Logf("مجموع 2 و 2 يساوي %d. تم اجتياز التحقق!", result)\n\n if result != 4 {\n t.Errorf("توقعنا 4، حصلنا على %d", result)\n }\n}\n\nشغل هذا الاختبار مع العلامة -v:
go test -v -run TestSum\n\nوسترى رسائل جميلة ومنظمة مباشرة في إخراج الاختبار.
\n\nلماذا t.Log أفضل من fmt.Println؟
\n- \n
- السياق: رسائل
t.Logترتبط تلقائيًا باختبار معين. في إخراج-v، ترى أي اختبار طبع ماذا. \n - التحكم: إخراج
t.Logيظهر فقط مع-vأو عند فشل الاختبار. هذا يعني أن سجلاتك لا تلوث وحدة التحكم عند التشغيل العادي. \n - الأمان: على عكس
fmt.Fprintf(os.Stderr, ...)، يعملt.Logبشكل صحيح مع الاختبارات المتوازية (t.Parallel) ولا يسبب حالة سباق (race condition). \n
الجانب المظلم للقوة: t.Error() و t.Fatal() كأداة إخراج
\n\nيستخدم العديد من المبتدئين t.Error() فقط لإيقاف الاختبار عند حدوث خطأ. لكن في الواقع، هذه طريقة ممتازة (وصحيحة!) لإخراج معلومات تشخيصية مهمة، خاصة عندما يفشل الاختبار.
السر هو أن الرسالة التي تُمرر إلى t.Error() أو t.Fatal() سيتم عرضها دائمًا، حتى بدون العلامة -v. هذا يجعلها مثالية لإخراج المعلومات الحرجة