طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 245 · ضمان جودة تطبيقات الويب
الدرس 23 · الوحدة 12: الاختبارات الشاملة وتقييمها

التكامل المستمر CI وبيئات الاختبار

كيف نضمن أن الاختبارات تُشغَّل فعلًا، وأن الكود المكسور لا يمرّ؟ ⏱ نحو 40 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تفهم التكامل المستمر CI.
  • تدرك كيف يمنع CI دمج الكود المكسور.
  • تفصل بيئات التطوير والاختبار والإنتاج.
  • تعزل بيانات الاختبار.

١الاختبار الذي يعمل وحده

اختباراتٌ ممتازة لا يشغّلها أحد عديمة الفائدة. التكامل المستمر CI يحلّ ذلك: خادمٌ يشغّل مجموعة الاختبارات آليًّا عند كل تغييرٍ يُرفَع إلى المستودع. إن فشل اختبار، يُمنَع الدمج ويُنبَّه الفريق فورًا. فلا يصل عيبٌ إلى الفرع الرئيس.

بلا CIمع CI
«نسيت تشغيل الاختبارات»تُشغَّل آليًّا دائمًا
العيب يُكتشَف متأخّرًايُكتشَف لحظة رفع الكود
«يعمل عندي فقط»يُبنى ويُختبَر في بيئةٍ نظيفة موحّدة

CI يحوّل الاختبار من عادةٍ فرديةٍ منسيّة إلى بوّابةٍ آلية. هو ما يجعل اختبار الانحدار (الدرس السابق) حقيقةً دائمة لا نيّةً حسنة.

٢كيف يبدو إعداد CI

ملفٌّ بسيط يصف ما يُشغَّل عند كل رفع (مثال GitHub Actions). الفكرة: ثبّت، ثم اختبر، وافشل البناء إن فشل اختبار:

# ci.yml — GitHub Actions
name: tests on: [push, pull_request] # عند كل رفعٍ أو طلب دمج jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: pip install -r requirements.txt - run: pytest --cov # يفشل البناء إن فشل اختبار

عند كل push: يجلب الكود، يثبّت الاعتمادات، يشغّل pytest مع التغطية. نتيجةٌ خضراء تسمح بالدمج، وحمراء تمنعه.

٣بيئات الاختبار

لا نختبر على بيئة المستخدمين الحيّة. نفصل البيئات كي لا يؤثّر الاختبار على الإنتاج:

البيئةالغرض
التطوير Devجهاز المبرمج؛ اختبارات سريعة أثناء الكتابة
الاختبار / التكامل Testبيئة نظيفة يشغّلها CI؛ تشبه الإنتاج
التجهيز Stagingنسخة طبق الأصل للإنتاج؛ اختبار القبول النهائيّ
الإنتاج Productionالمستخدمون الحقيقيّون؛ لا نختبر عليها

توقّع وتحقّق

CI يشغّل الاختبارات:

إن فشل اختبارٌ في CI:

لا نختبر على بيئة:

بيانات الاختبار يجب أن تكون:

الخلاصة

تحدٍّ برمجي: بوّابة CI

متوسط

حاكِ بوّابة CI: دالة ci_gate تأخذ قائمة نتائج اختبارات (True=نجح) وتعيد "pass" إن نجحت كلّها وإلا "fail". اطبع نتيجة مجموعتين.

المطلوب:
  • أعِد "pass" فقط إن كانت كل النتائج True.
  • اطبع نتيجة [True,True,True] و[True,False,True].

ابدأ من هذا الكود، واضغط ▶ شغّل هنا لتكتب حلّك وتجرّبه مباشرة:

main.py
def ci_gate(results):    # "pass" إن نجحت كل الاختبارات وإلا "fail"    passprint(ci_gate([True, True, True]))print(ci_gate([True, False, True]))
المطلوب×
pass
fail
💡 تلميح 1
all(results) يكون True إن نجحت كلّها.
💡 تلميح 2
return "pass" if all(results) else "fail".

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

main.py
def ci_gate(results):    return "pass" if all(results) else "fail"print(ci_gate([True, True, True]))print(ci_gate([True, False, True]))
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس