← رجوع

كيف يعمل Testing فعلًا داخل Laravel

R

UNIXMAN

Feb 27, 2026

Article Image

Testing في Laravel: كيف تفكّر بالاختبارات قبل ما تكتب أول Test

أغلب المطورين يتعامل مع الاختبارات كمرحلة لاحقة: المشروع يشتغل أولاً… وبعدها نحاول نضيف Tests. لكن مع الوقت تكتشف إن المشكلة مو في كتابة الاختبار، المشكلة في فهم ماذا يجب اختباره أصلًا. Laravel لا يقدّم PHPUnit كأداة إضافية، بل يبني حولها نظام Testing كامل مرتبط بدورة حياة التطبيق نفسها.

ما هو PHPUnit داخل Laravel فعليًا؟

PHPUnit هو محرك الاختبارات، أما Laravel فهو الطبقة التي تجعل اختبار التطبيق ممكن بدون تعقيد. عند تنفيذ:
php artisan test
Laravel يقوم بـ:
  • تشغيل PHPUnit
  • إنشاء Application Instance
  • تحميل Service Container
  • تهيئة البيئة الخاصة بالاختبار
بمعنى أن الاختبار يعمل داخل نسخة حقيقية من التطبيق.

أنواع الاختبارات في Laravel

Laravel يقسم الاختبارات منطقيًا إلى مستويين أساسيين.

1) Unit Tests

Unit Test يختبر جزء صغير جدًا من الكود بدون تشغيل النظام بالكامل. مثال:
  • Class
  • Service
  • Helper
  • Logic منفصل
مثال:
class PriceCalculator
{
    public function total($price, $tax)
    {
        return $price + ($price * $tax);
    }
}
الاختبار:
test('calculate total price', function () {
    $calc = new PriceCalculator();

    expect($calc->total(100, 0.15))
        ->toBe(115);
});
هنا:
  • لا Database
  • لا HTTP
  • لا Laravel Models
فقط منطق برمجي. هدفه السرعة والعزل.

2) Feature Tests

Feature Test يختبر سلوك النظام بالكامل. مثلاً:
  • Request → Controller → Model → Database → Response
مثال:
test('user can create post', function () {

    $user = User::factory()->create();

    $response = $this->actingAs($user)
        ->post('/posts', [
            'title' => 'Test Post'
        ]);

    $response->assertStatus(302);

    $this->assertDatabaseHas('posts', [
        'title' => 'Test Post'
    ]);
});
هنا الاختبار يشمل:
  • Authentication
  • Routing
  • Validation
  • Database
هذا اختبار سلوك التطبيق وليس دالة واحدة.

الفرق الحقيقي بين Unit و Feature

Unit Feature
سريع جدًا أبطأ
منطق فقط النظام كامل
بدون Database يستخدم Database
عزل كامل تكامل حقيقي
المشاريع الصحية تستخدم الاثنين. Unit يمنع الأخطاء المنطقية، Feature يمنع انهيار النظام.

اختبار HTTP Layer

Laravel يسمح بمحاكاة الطلبات بدون تشغيل سيرفر فعلي.
$this->get('/dashboard')
     ->assertOk();
أو:
$this->postJson('/api/login', [
    'email' => '[email protected]',
    'password' => 'secret'
])->assertJsonStructure([
    'token'
]);
لا يوجد Browser هنا، فقط محاكاة Kernel داخليًا.

Testing Database بدون تخريب البيانات

Laravel يوفر Trait مهم:
use RefreshDatabase;
هذا يقوم بـ:
  • إعادة Migration قبل كل Test
  • تنظيف البيانات تلقائيًا
بالتالي كل اختبار يبدأ ببيئة نظيفة.

Factories: أساس الاختبارات الواقعية

بدل إنشاء بيانات يدويًا:
User::create([...]);
نستخدم Factory:
User::factory()->create();
أو:
Post::factory()
    ->count(5)
    ->for(User::factory())
    ->create();
Factories تجعل الاختبار قريب من الواقع.

Mocking داخل Laravel

أحيانًا لا تريد استدعاء خدمة حقيقية. مثلاً API خارجي. Laravel يدعم Mock بسهولة:
$this->mock(PaymentService::class, function ($mock) {
    $mock->shouldReceive('charge')
         ->once()
         ->andReturn(true);
});
الاختبار هنا يتحقق من السلوك، بدون تنفيذ الاتصال الحقيقي.

اختبار Events و Jobs و Notifications

Laravel يسمح بتجميد الأنظمة الجانبية. مثال Events:
Event::fake();

OrderCreated::dispatch();

Event::assertDispatched(OrderCreated::class);
Jobs:
Queue::fake();

ProcessOrder::dispatch();

Queue::assertPushed(ProcessOrder::class);
Notifications:
Notification::fake();

Notification::assertSentTo(
    $user,
    OrderNotification::class
);
بهذا الشكل تختبر التدفق بدون تنفيذ فعلي.

Pest vs PHPUnit

Laravel يدعم الاثنين. PHPUnit:
  • Class based
  • تقليدي
Pest:
  • Functional style
  • أقل Boilerplate
  • قراءة أسرع
كلاهما يستخدم نفس المحرك. الاختلاف في أسلوب الكتابة فقط.

متى تعرف أن مشروعك يحتاج Testing فعلاً؟

عادة عند حدوث أحد هذه الأمور:
  • الخوف من تعديل كود قديم
  • ظهور Bugs بعد كل Feature
  • Refactoring صعب
  • اعتماد كامل على الاختبار اليدوي
الاختبارات ليست ضمان خلو الأخطاء، بل ضمان أن التغييرات لا تكسر ما كان يعمل.

الخلاصة

Testing في Laravel ليس كتابة Assertions، بل بناء طبقة ثقة فوق التطبيق. Unit Tests تحمي المنطق، Feature Tests تحمي السلوك، وMocking يسمح بعزل العالم الخارجي. المشروع الذي يملك اختبارات جيدة، يمكن تطويره بلا خوف.