تغطية الكود بالاختبارات في C#: من المقاييس إلى الجودة

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

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

ابدأ الدورة

لماذا الاختبارات "الخضراء" ليست نصراً بعد؟

\n\n

تخيل: لقد كتبت مئة اختبار وحدة، جميعها تمر بعلامة خضراء، خط أنابيب CI سعيد، والمدير راضٍ. ولكن بعد شهر، ينهار وظيفة حرجة في الإنتاج. قصة مألوفة؟ غالباً ما تكمن المشكلة في أننا نختبر سيناريوهات خاطئة أو نتخطى فروعاً كاملة من الكود.

\n\n

تغطية الكود بالاختبارات (code coverage) ليست مجرد مقياس عصري للتقرير. إنها مصباحك اليدوي في غرفة مظلمة من عدم اليقين. عندما بدأت العمل مع C#، اعتقدت أن تغطية 80% هي المثالية. لكنني أدركت لاحقاً: يمكن أن يكون لديك تغطية 100% للأسطر ومع ذلك تفوت خطأ في منطق التفرع. لذلك سنفهم اليوم كيفية قياس التغطية في C# بشكل صحيح، وما هي الأدوات التي تساعد حقاً، وأي المقاييس يجب تتبعها.

\n\n

ما هي تغطية الكود ولماذا هي مهمة لمطور C#؟

\n\n

ببساطة، تغطية الكود تُظهر النسبة المئوية للكود المصدري لتطبيقك الذي تم تنفيذه أثناء تشغيل الاختبارات. إذا كتبت اختباراً يستدعي الدالة CalculateDiscount()، لكنه لا يتحقق من الفرع if (isPremiumUser)، فإن هذا الفرع يبقى "غير مغطى".

\n\n

بالنسبة لمطور C#، التغطية هي مؤشر لأمرين:

\n
    \n
  • الثقة في إعادة الهيكلة — هل يمكن تغيير الكود دون الخوف من كسر شيء ما؟
  • \n
  • اكتمال الاختبارات — هل نسينا الحالات الحدودية؟
  • \n
\n\n

لكن هناك فارق مهم: تغطية الكود بالاختبارات في C# لا تضمن عدم وجود أخطاء. إنها تخبر فقط أن أسطراً معينة تم تنفيذها. لهذا السبب لا ننظر فقط إلى النسبة المئوية، بل إلى مقاييس محددة.

\n\n

المقاييس الرئيسية لتغطية الكود في .NET

\n\n

عند تشغيل تحليل التغطية في C#، ستواجه عدة أنواع من المقاييس. دعنا نحلل كل منها بمثال على كود حقيقي.

\n\n

Line Coverage (تغطية الأسطر)

\n

أبسط مقياس. يحسب عدد أسطر الكود التي تم تغطيتها بالاختبارات. مثال:

\n\n
public int Add(int a, int b)\n{\n    if (a < 0)          // سطر 1\n        return 0;       // سطر 2\n    return a + b;        // سطر 3\n}
\n\n

إذا كان اختبارك يستدعي Add(5, 3)، فسيتم تنفيذ السطرين 1 و 3. سيبقى السطر 2 غير مغطى. ستظهر تغطية الأسطر 66% (2 من 3 أسطر).

\n\n

Branch Coverage (تغطية التفرعات)

\n

مقياس أكثر دقة. يأخذ في الاعتبار جميع المسارات الممكنة للتنفيذ. في مثالنا، هناك مساران: عندما a < 0 وعندما لا يكون كذلك. إذا اختبرت فقط حالة الرقم الموجب، ستكون تغطية التفرعات 50%.

\n\n

غالباً ما تكشف تغطية التفرعات "الثغرات" في الاختبارات. أوصي بالسعي لتحقيق 80%+ وفقاً لهذا المقياس تحديداً.

\n\n

Cyclomatic Complexity وعلاقتها بالتغطية

\n

على الرغم من أنه ليس مقياس تغطية مباشراً، إلا أن التعقيد الحلقي يوضح عدد الاختبارات التي يجب كتابتها للتغطية الكاملة. كلما زاد تعقيد الدالة، زادت الحاجة إلى اختبارات أكثر. إذا رأيت دالة بتعقيد حلقي 15 وتغطية 90% — فمن المحتمل أنك لا تختبر جميع السيناريوهات.

\n\n

أدوات قياس تغطية الكود في C#

\n\n

في نظام .NET البيئي، هناك عدة أدوات قوية. سأخبرك عن الثلاثة الأكثر شيوعاً التي عملت بها بنفسي.

\n\n

Coverlet — مجاني ومدمج في .NET

\n

إذا كنت تستخدم .NET 6+، فإن Coverlet متاح بالفعل عبر NuGet. هذه أداتي المفضلة لـ CI/CD لأنها لا تتطلب تثبيت برامج إضافية.

\n\n

التثبيت:

\n
dotnet add package coverlet.msbuild\ndotnet add package coverlet.collector
\n\n

التشغيل مع تقرير:

\n
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
\n\n

ستحصل على ملف coverage.opencover.xml، والذي يمكن تصوره باستخدام ReportGenerator:

\n
dotnet tool install -g dotnet-reportgenerator-globaltool\nreportgenerat                

المدونات

توصيات الكتب