الاختبار الطفري في PHP: قتل الاختبارات لجعلها تعمل

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

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

ابدأ الدورة

هل اختباراتك مجرد وهم للأمان؟



تخيل: لديك 95% من تغطية الكود، جميع الاختبارات خضراء، وCI/CD يمر. هل أنت متأكد أن كود PHP الخاص بك محمي من الانحدار؟ لكن هل هذا صحيح حقًا؟



لقد عشت أنا نفسي في هذا الوهم لفترة طويلة، حتى واجهت موقفًا: كان الاختبار يمر، على الرغم من أنني استبدلت عن طريق الخطأ && بـ || في شرط حاسم. الاختبار ببساطة لم يتحقق من هذا الفرع. كانت التغطية 100%، لكن المنطق لم يكن كذلك.



تعرف على: الاختبار الطفري (mutation testing) — منهجية تقوم بلا رحمة بـ"قتل" اختباراتك لمعرفة مدى موثوقيتها الفعلية. في هذه المقالة، سنشرح كيفية تطبيقها في PHP باستخدام الأداة القوية Infection، ولماذا يغير ذلك قواعد اللعبة.



ما هو الاختبار الطفري ولماذا هو مطلوب؟



الاختبار الطفري هو نهج يتم فيه إجراء تغييرات صغيرة متعمدة (طفرات) على كود المصدر الخاص بك. على سبيل المثال، يتم تغيير العامل + إلى -، true إلى false، أو حذف سطر كامل. بعد كل طفرة، يتم تشغيل اختباراتك.



إذا فشل الاختبار — يتم "قتل" الطفرة، مما يعني أن الاختبار يتحقق بالفعل من هذا الجزء من الكود. إذا مر الاختبار — "نجت" الطفرة. هذه إشارة مقلقة: إما أن الاختبار لا يتحقق من هذا الشرط، أو أنه مكتوب بشكل غير صحيح.



على عكس مقياس "تغطية الكود" (code coverage) الذي يظهر فقط أي الأسطر تم تنفيذها، يتحقق الاختبار الطفري من جودة الفحوصات. النسبة العالية من التغطية ليست ضمانًا، بينما مؤشر درجة الطفرات (Mutation Score Indicator, MSI) هو مقياس حقيقي للموثوقية.



لماذا هذا مهم لمطور PHP؟

  • اكتشاف الاختبارات "الميتة" — تلك التي تكون دائمًا خضراء ولكنها لا تختبر شيئًا.
  • كشف الثغرات في المنطق — مثل الشروط الحدودية المفقودة.
  • زيادة الثقة أثناء إعادة الهيكلة — تعرف بالضبط أي الاختبارات تحمي الكود.
  • توفير الوقت — بدلاً من التدقيق اليدوي للاختبارات، تحصل على تقرير تلقائي.


أدوات الاختبار الطفري في PHP



الرائد في ساحة PHP هو Infection (المعروف سابقًا باسم Humbug). يتكامل بسهولة مع PHPUnit و Pest، ويدعم العديد من الطفرات ويقدم تقارير مرئية.



خيارات أخرى: Humbug (السلف، لكنه أقل نشاطًا) و Mutagen (تجريبي). سنركز على Infection — فهو المعيار الحديث.



التطبيق العملي: إعداد Infection في المشروع



لنقم بتثبيت Infection وتشغيله على مثال حقيقي. لنفترض أن لدينا فئة بسيطة لحساب الخصم:



<?php// src/DiscountCalculator.phpclass DiscountCalculator{    public function calculate(float $price, bool $isPremium): float    {        if ($isPremium) {            return $price * 0.9; // خصم 10%        }

return $price; }}


واختبارها:



<?php// tests/DiscountCalculatorTest.phpuse PHPUnit\\Framework\\TestCase;

class DiscountCalculatorTest extends TestCase{ public function testPremiumDiscount(): void { $calculator = new DiscountCalculator(); $result = $calculator->calculate(100.0, true); $this->assertEquals(90.0, $result); }

public function testRegularPrice(): void { $calculator = new DiscountCalculator(); $result = $calculator->calculate(100.0, false); $this->assertEquals(100.0, $result); }}


التغطية — 100%. لكن دعنا نتحقق بالطفرات.



تثبيت وتشغيل Infection



composer require --dev infection/infection./vendor/bin/infection


بعد

المدونات

توصيات الكتب