اختبار الوحدة الخاص بك يكذب (وأنت تعلم ذلك)
\n\nتخيل: لقد كتبت 50 اختبار وحدة، جميعها خضراء، والتغطية 90%. أنت راضٍ. ولكن بعد أسبوع، ينهار الإنتاج. اتضح أن طريقتك SortArray() تعمل بشكل ممتاز مع [1, 2, 3] و [3, 1, 2]، ولكنها تفشل مع [int.MaxValue, -1, 0]. هل هذا مألوف؟
مشكلة اختبارات الوحدة التقليدية هي تحيز المطور. أنت تكتب اختبارات بناءً على البيانات التي تتوقعها. المخترقون، المستخدمون الحقيقيون، والحالات الحدودية العشوائية تعيش بقواعد مختلفة.
\n\nهنا يأتي دور الاختبار القائم على الخصائص في C# (أو الاختبار المبني على الخصائص). بدلاً من التحقق من "إذا كان A، فإن B"، فإنك تصف خصائص يجب أن تكون صحيحة دائمًا. ويقوم الإطار تلقائيًا بتوليد مئات من بيانات الإدخال العشوائية والتحقق من افتراضاتك.
\n\nفي هذه المقالة، سنشرح كيفية تطبيق الاختبار القائم على الخصائص في C# باستخدام مكتبة FsCheck، وسنكتب أمثلة حقيقية ونرى كيف يكتشف الأخطاء التي تفوتها الاختبارات العادية.
\n\nما هو الاختبار القائم على الخصائص؟
\n\nالاختبار القائم على الخصائص هو نهج تقوم فيه بصياغة ثوابت (خصائص) لبرنامجك. على سبيل المثال:
\n- \n
- "بعد الفرز، لا يتغير طول المصفوفة" \n
- "عكس ترتيب السلسلة النصية مرتين يعطي السلسلة الأصلية" \n
- "مجموع رقمين موجبين يكون دائمًا موجبًا" \n
يقوم الإطار (مثل FsCheck) بتوليد عشرات ومئات من بيانات الإدخال العشوائية والتحقق من أن الخاصية تتحقق للجميع. إذا تم العثور على مثال مضاد، يفشل الاختبار وستحصل على القيم المحددة التي كسرت الكود.
\n\nعلى عكس اختبارات الوحدة، أنت لا تكتب Assert.AreEqual(3, Add(1,2)). أنت تكتب Assert(x + y == y + x) - وتختبر خاصية التبادلية لآلاف أزواج الأرقام.
الفرق عن اختبارات الوحدة العادية
\n\n| اختبارات الوحدة | اختبارات قائمة على الخصائص |
|---|---|
| تتحقق من أمثلة محددة | تتحقق من قوانين عامة |
| البيانات يحددها المطور | البيانات يولدها الإطار |
| تفوت الحالات الحدودية | تستكشف الحدود تلقائيًا |
| سهلة القراءة | تتطلب تفكيرًا مجردًا |
مكتبة FsCheck: أداتك الرئيسية
\n\nفي عالم C#، المعيار الفعلي للاختبار القائم على الخصائص هو FsCheck (مشتق أصلاً من مكتبة QuickCheck الخاصة بـ Haskell). يتكامل مع xUnit و NUnit و MSTest.
\n\nالتثبيت بسيط:
\ndotnet add package FsCheck\ndotnet add package FsCheck.Xunit // للتكامل مع xUnit\n\nيمكن لـ FsCheck توليد بيانات عشوائية للأنواع البدائية (int، string، float)، والقوائم، والمصفوفات، والتوابل، وحتى الأنواع المخصصة (من خلال مولدات مخصصة).
كتابة أول اختبار قائم على الخصائص في C#
\n\nلنبدأ بشيء بسيط: التحقق من أن عملية جمع الأعداد الصحيحة هي عملية تبادلية.
\n\nusing FsCheck;\nusing FsCheck.Xunit;\n\npublic class AdditionTests\n{\n [Property]\n public bool Commutative_Addition(int x, int y)\n {\n return x + y == y + x;\n }\n}\n\nقم بتشغيل الاختبار. سيقوم FsCheck بتوليد 100 زوج عشوائي من int (افتراضيًا) والتحقق من الخاصية. إذا لم يتم العثور على مثال مضاد، يكون الاختبار أخضر. إذا كنا قد أخطأنا (على سبيل المثال، كتبنا x - y == y - x)، سيفشل الاختبار مع مثال محدد: (5, 3) - لأن 5 - 3 != 3 - 5.
تحليل الكود
\n- \n
- [Property] - سمة تخبر FsCheck أن هذا اختبار قائم على الخصائص. \n
- الطريقة ترجع
bool- إذا أعادتfalse، يفشل الاختبار. \n - المعلمات
int x, int y- سيقوم FsCheck تلقائيًا بتعويض قيم عشوائية.