اختبارات Go: الوحدة، التكامل، e2e — دليل شامل

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

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

ابدأ الدورة

مقدمة: لماذا تعتبر الاختبارات في لغة Go مهمة؟

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

في هذه المقالة، سنقوم بتحليل ثلاثة مستويات رئيسية للاختبارات: الوحدة، التكامل، و e2e (من البداية إلى النهاية). ستتعلم كيف تختلف هذه المستويات، ومتى يتم تطبيقها، وكيفية كتابة اختبارات فعالة في لغة Go. ستكون المادة مفيدة لكل من المبتدئين والمطورين ذوي الخبرة الذين يتطلعون إلى تنظيم معرفتهم.



1. اختبارات الوحدة (Unit Testing)

اختبارات الوحدة هي أساس هرم الاختبارات. تتحقق هذه الاختبارات من عمل الدوال الفردية، أو التوابع، أو الوحدات بشكل منفصل عن التبعيات الخارجية (قواعد البيانات، الشبكة، نظام الملفات).



المبادئ الأساسية لاختبارات الوحدة في Go

  • العزل: يجب ألا يعتمد الكود الذي يتم اختباره على الخدمات الخارجية.
  • السرعة: يتم تنفيذ اختبارات الوحدة خلال أجزاء من الثانية.
  • الحتمية: يجب ألا تتغير نتيجة الاختبار من تشغيل إلى آخر.


مثال على اختبار وحدة بسيط

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

// math.gopackage math

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

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

// math_test.gopackage math

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 ./...



الاختبارات المعتمدة على الجداول (Table-driven Tests)

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

func TestAddTable(t *testing.T) {    tests := []struct {        a, b, expected int    }{        {1, 1, 2},        {0, 0, 0},        {-1, 1, 0},        {100, 200, 300},    }

for _, tt := range tests { result := Add(tt.a, tt.b) if result != tt.expected { t.Errorf("Add(%d, %d) = %d; want %d", tt.a, tt.b, result, tt.expected) } }}

نصيحة: استخدم t.Run() لإنشاء اختبارات متداخلة بأسماء واضحة — فهذا يحسن من قابلية قراءة التقارير.



2. اختبارات التكامل (Integration Testing)

تتحقق اختبارات التكامل من التفاعل بين مكونات النظام: قاعدة البيانات، واجهة برمجة التطبيقات (API)، الخدمات الخارجية. على عكس اختبارات الوحدة، هنا نقوم بتشغيل تبعيات حقيقية (أو شبه حقيقية).



مميزات اختبارات التكامل في Go

  • غالبًا ما تتطلب إعداد البيئة (مثل، قاعدة بيانات اختبارية).
  • يمكن استخدام build tags لفصل اختبارات الوحدة عن اختبارات التكامل.
  • يتم تشغيلها بشكل أبطأ، لذلك يتم تنفيذها بشكل منفصل.


مثال: اختبار عمليات قاعدة البيانات (PostgreSQL)

لنقم بإنشاء ملف مع علامة integration:

// db_test.go//go:build integration

package db

import ( "database/sql" "testing")

func TestSaveUser(t *testing.T) { // الاتصال بقاعدة البيانات الاختبارية dsn := "host=localhost user=test password=test dbname=testdb sslmode=disable" db, err := sql.Open("postgres", dsn) if err != nil { t.Fatalf("فشل الاتصال بقاعدة البيانات: %v", err) } defer db.Close()

// تنظيف البيانات قبل الاختبار _, _ = db.Exec("TRUNCATE TABLE users")

// تنفيذ العملية التي يتم اختبارها user := User{Name: "Alice", Email: "alice@example.com"}

المدونات

توصيات الكتب