الأعداد الصحيحة
يمكنك العثور على كل كود هذا الفصل هنا
تعمل الأعداد الصحيحة كما تتوقع. لنكتب دالة Add لتجربة الأمر. أنشئ ملف اختبار اسمه adder_test.go واكتب فيه هذا الكود.
ملاحظة: يمكن لملفات مصدر Go أن تحتوي على package واحدة فقط لكل مجلد. تأكد من تنظيم ملفاتك في حزم خاصة بها. إليك شرحًا جيدًا لهذا.
ورُبما يبدو مجلد مشروعك هكذا:
learnGoWithTests
|
|-> helloworld
| |- hello.go
| |- hello_test.go
|
|-> integers
| |- adder_test.go
|
|- go.mod
|- README.mdاكتب الاختبار أولًا
package integers
import "testing"
func TestAdder(t *testing.T) {
sum := Add(2, 2)
expected := 4
if sum != expected {
t.Errorf("expected '%d' but got '%d'", expected, sum)
}
}ستلاحظ أننا نستخدم %d بدلًا من %q في نصوص التنسيق، لأننا نريد طباعة عدد صحيح لا نص.
ولاحظ أيضًا أننا لم نعد نستخدم الحزمة main، بل عرّفنا حزمة اسمها integers، وهي كما يوحي الاسم ستجمع الدوال الخاصة بالتعامل مع الأعداد الصحيحة مثل Add.
جرّب تشغيل الاختبار
شغّل الاختبار بالأمر go test.
وافحص خطأ الترجمة:
./adder_test.go:6:9: undefined: Add
اكتب أصغر قدر من الكود ليعمل الاختبار وافحص مخرجاته الفاشلة
اكتب كودًا كافيًا لإرضاء المترجم ولا شيء غير ذلك، وتذكّر أننا نريد التحقق أن اختبارنا يفشل للسبب الصحيح.
package integers
func Add(x, y int) int {
return 0
}وتذكّر أنه عندما يكون لديك أكثر من وسيط من النوع نفسه (عددان صحيحان في حالتنا) فبدلًا من (x int, y int) يمكنك اختصارها إلى (x, y int).
شغّل الاختبارات الآن، وينبغي أن نكون سعداء لأن الاختبار يبلّغ عن المشكلة بشكل صحيح.
adder_test.go:10: expected '4' but got '0'
وإذا كنت قد لاحظت، فقد تعلمنا القيمة المُرجعة المُسمّاة في الفصل السابق، لكننا لا نستخدمها هنا. وينبغي استخدامها عمومًا عندما لا يكون معنى النتيجة واضحًا من السياق، وفي حالتنا هذه من الواضح تمامًا أن دالة Add ستجمع البارامترات. ويمكنك مراجعة هذه الصفحة لتفاصيل أكثر.
اكتب كودًا كافيًا لنجاح الاختبار
بأدق معنى للتطوير الموجه بالاختبار، ينبغي الآن أن نكتب أصغر قدر من الكود يجعل الاختبار ينجح. وقد يفعل مبرمج متزمت هذا:
func Add(x, y int) int {
return 4
}ها ها! لقد خُدعنا مرة أخرى، فالتطوير الموجه بالاختبار مهزلة، أليس كذلك؟
يمكننا كتابة اختبار آخر بأرقام مختلفة لإجبار ذلك الاختبار على الفشل، لكن ذلك يشبه لعبة القط والفأر.
وبعد أن نعتاد على صياغة Go أكثر، سأقدّم تقنية تسمى “الاختبار القائم على الخصائص” (Property Based Testing)، وهي التي ستكفّ المطورين عن الإزعاج وتساعدك على إيجاد الأخطاء.
في الوقت الحالي، لنصلح الكود على النحو الصحيح:
func Add(x, y int) int {
return x + y
}وإذا أعدت تشغيل الاختبارات، ينبغي أن تنجح.
إعادة الهيكلة
لا يوجد الكثير في الكود الفعلي يمكننا تحسينه هنا.
لقد استكشفنا سابقًا كيف أن تسمية وسيط الإرجاع تُظهره في التوثيق، وكذلك في معظم محررات النصوص.
وهذا رائع لأنه يعزز سهولة استخدام الكود الذي تكتبه. فمن الأفضل أن يستطيع المستخدم فهم استخدام كودك بمجرد النظر إلى توقيع النوع (type signature) والتوثيق.
ويمكنك إضافة توثيق للدوال بالتعليقات، وستظهر هذه في Go Doc تمامًا كما تراها في توثيق المكتبة القياسية.
// Add takes two integers and returns the sum of them.
func Add(x, y int) int {
return x + y
}أمثلة قابلة للاختبار (Testable Examples)
إذا أردت أن تذهب خطوة إضافية فعلًا، يمكنك كتابة أمثلة قابلة للاختبار. وستجد الكثير من الأمثلة في توثيق المكتبة القياسية.
فكثيرًا ما تصبح أمثلة الكود الموجودة خارج قاعدة الكود، مثل ملف readme، قديمة وغير صحيحة مقارنة بالكود الفعلي لأن أحدًا لا يفحصها.
أما دوال الأمثلة فتُترجم في كل مرة تُنفَّذ فيها الاختبارات. ولأن المترجم يتحقق من هذه الأمثلة، يمكنك أن تثق أن أمثلة توثيقك تعكس دائمًا سلوك الكود الحالي.
تبدأ دوال الأمثلة بـ Example (تمامًا كما تبدأ دوال الاختبار بـ Test)، وتُكتب في ملفات _test.go الخاصة بالحزمة. أضف الدالة ExampleAdd التالية إلى ملف adder_test.go.
func ExampleAdd() {
sum := Add(1, 5)
fmt.Println(sum)
// Output: 6
}(إذا لم يكن محرّرك يستورد الحزم تلقائيًا، فستفشل خطوة الترجمة لأنك ستفتقد import "fmt" في adder_test.go. ومن المُوصى بشدة أن تبحث عن كيفية إصلاح هذه الأخطاء تلقائيًا في المحرر الذي تستخدمه.)
وإضافة هذا الكود ستجعل المثال يظهر في توثيقك، ما يجعل كودك أسهل وصولًا. وإذا تغيّر كودك يومًا بحيث يصبح المثال غير صالح، فسيفشل البناء.
وبتشغيل مجموعة اختبارات الحزمة، نرى أن دالة المثال ExampleAdd تُنفَّذ دون أي ترتيب إضافي منا:
$ go test -v
=== RUN TestAdder
--- PASS: TestAdder (0.00s)
=== RUN ExampleAdd
--- PASS: ExampleAdd (0.00s)ولاحظ الصيغة الخاصة للتعليق // Output: 6. فالمثال دائمًا يُترجم، لكن إضافة هذا التعليق تعني أنه سيُنفَّذ أيضًا. جرّب أن تحذف التعليق // Output: 6 مؤقتًا، ثم شغّل go test، وسترى أن ExampleAdd لم تعد تُنفَّذ.
والأمثلة بدون تعليقات المخرجات مفيدة لعرض كود لا يمكن تشغيله كاختبارات وحدة، مثل الكود الذي يتصل بالشبكة، مع ضمان أن المثال يُترجم على الأقل.
ولعرض توثيق الأمثلة، لنلقِ نظرة سريعة على pkgsite. قبل الانتقال إلى مجلد مشروعك، تأكد من تثبيت pkgsite بالأمر go install golang.org/x/pkgsite/cmd/pkgsite@latest، ثم شغّله بـ pkgsite -open .، وسيفتح لك متصفحًا يشير إلى http://localhost:8080. وسترى هناك قائمة بكل حزم المكتبة القياسية في Go، بالإضافة إلى الحزم الخارجية التي ثبّتها، وسترى تحت ذلك توثيق المثال الخاص بـ github.com/quii/learn-go-with-tests. اتبع ذلك الرابط، ثم ابحث تحت Integers، ثم تحت func Add، ثم وسّع Example، وسترى المثال الذي أضفته من أجل sum := Add(1, 5).
وإذا نشرت كودك مع الأمثلة على رابط عام، فستنشر توثيق كودك على pkg.go.dev. وعلى سبيل المثال، هنا الواجهة النهائية لهذا الفصل. وتتيح لك هذه الواجهة البحث في توثيق حزم المكتبة القياسية والحزم الخارجية.
الخلاصة
ما غطيناه:
- مزيد من التدريب على سير عمل التطوير الموجه بالاختبار
- الأعداد الصحيحة والجمع
- كتابة توثيق أفضل ليستطيع مستخدمو كودك فهم استخدامه بسرعة
- أمثلة لكيفية استخدام كودك، تُفحص كجزء من اختباراتك