ليلة لا تُنسى… وبَج “Bug” كاد أن يكلّفنا كل شيء
بتذكّرها زي كأنها مبارح. كانت ليلة خميس، وإحنا في الشركة الناشئة اللي كنت أشتغل فيها، كان عنّا موعد إطلاق ميزة جديدة ومهمة يوم الأحد. الأجواء كانت مشحونة، والقهوة شغّالة 24 ساعة. واحد من المبرمجين الشاطرين، شب اسمه خالد، عمل تغيير “بسيط” على الكود عشان يحل مشكلة صغيرة في الواجهة الأمامية. التغيير كان سطرين ثلاثة، وشكله بريء جدًا.
بسبب ضغط الوقت، ما حدا فينا فكّر يعمل Regression Testing كامل. قلنا “يا زلمة، شو هالتغيير البسيط، مش مستاهل”. اعتمدنا على الاختبار اليدوي السريع، وكل شي كان تمام. رفعنا الكود على الـ Staging server واستنينا يوم الأحد بفارغ الصبر.
يوم الإطلاق، وبعد ما احتفلنا لكم دقيقة، بلشت توصلنا الإشعارات. نظام الدفع الرئيسي في التطبيق توقف عن العمل! صار في حالة هلع في المكتب. كيف صار هيك؟ بعد ساعات من التحقيق والـ”ديوَان” (التحقيق والبحث الطويل)، اكتشفنا إنه التغيير “البسيط” اللي عمله خالد، وبشكل غير مباشر بالمرة، عطّل جزئية حساسة في عملية تأكيد الدفع.
هذيك الليلة، واحنا بنصلّح المشكلة وبنعتذر للمستخدمين، أقسمت إني ما راح أسمح لهيك موقف يتكرر. مش منطق إنه جودة منتجنا وثقة عملائنا تكون معلّقة بـ “بلكي” و “يمكن”. من هون بلشت رحلتي الحقيقية مع بناء أنظمة CI/CD قوية ومخصصة للاختبارات. مش بس عشان نلاقي الأخطاء، بل عشان نبني ثقة في كل سطر كود بنكتبه. تعالوا أحكيلكم كيف بنبني شبكة الأمان هاي.
ما هو الـ CI/CD Pipeline ولماذا هو ضروري للاختبارات؟
قبل ما ندخل في التفاصيل التقنية، خلينا نبسّط المفاهيم. تخيّل عندك خط إنتاج في مصنع. كل قطعة بتمر على مراحل فحص وتدقيق تلقائية قبل ما تطلع من المصنع. لو أي قطعة فيها خلل، الخط كله بوقّف، والكل بعرف وين المشكلة فورًا. هذا بالضبط هو الـ CI/CD Pipeline في عالم البرمجة.
- التكامل المستمر (Continuous Integration – CI): هو عملية دمج التغييرات البرمجية من كل المطورين في مستودع مركزي بشكل مستمر. مع كل عملية دمج، يتم بناء المشروع وتشغيل الاختبارات تلقائيًا. الهدف؟ اكتشاف المشاكل في وقت مبكر جدًا.
- التسليم/النشر المستمر (Continuous Delivery/Deployment – CD): بعد نجاح مرحلة الـ CI، يتم نشر الكود تلقائيًا على بيئة الاختبار (Staging) أو حتى بيئة الإنتاج (Production).
لما نربط اختبارات الأوتوميشن (Automation Tests) مع هذا الـ Pipeline، احنا فعليًا بنحوّلها من مجرد سكربتات بنشغلها يدويًا وقت ما نتذكر، إلى حارس أمين وشبكة أمان تعمل 24/7. أي تغيير بيكسر جزئية مهمة في النظام، الـ Pipeline بيكشفه فورًا وبيرفض التغيير، وبيبعتلنا إشعار يقول: “يا جماعة، في مشكلة هون!”.
أركان الـ Pipeline الأساسية لاختبارات الأوتوميشن
عشان نبني Pipeline متكامل، لازم يكون عنّا مجموعة من الأدوات اللي بتشتغل مع بعضها بانسجام. هاي هي الأركان الأساسية:
- مصدر الكود (Source Code Repository): المكان اللي بنحفظ فيه الكود تبعنا وكود الاختبارات. أشهر الأمثلة: GitHub, GitLab, Bitbucket.
- خادم الـ CI/CD (The CI/CD Server): العقل المدبّر للعملية. هو اللي بيراقب التغييرات على الكود وبشغّل الأوامر المكتوبة في ملف الإعدادات. أشهر الأدوات: GitHub Actions (مدمج مع GitHub)، GitLab CI (مدمج مع GitLab)، و Jenkins (خادم مفتوح المصدر وقوي جدًا).
- إطار عمل الاختبار (Testing Framework): الأداة اللي بنكتب فيها الاختبارات نفسها. مثل Cypress, Playwright, Selenium, أو أي إطار عمل آخر.
- بيئة الاختبار (Test Environment): المكان الفعلي اللي راح تشتغل فيه الاختبارات. ممكن يكون جهاز افتراضي (VM) أو الأفضل، حاوية دوكر (Docker Container) لضمان بيئة نظيفة ومتطابقة في كل مرة.
- التقارير والإشعارات (Reporting & Notifications): الأدوات اللي بتساعدنا نفهم نتائج الاختبارات بسهولة (مثل Allure Report) واللي بتبلّغنا بالنتائج (مثل إشعارات Slack أو البريد الإلكتروني).
بناء الـ Pipeline خطوة بخطوة مع GitHub Actions
بما إنه GitHub Actions سهل ومدمج، راح نستخدمه كمثال رئيسي. المبادئ اللي راح نطبقها هون بتنطبق على Jenkins (باستخدام Jenkinsfile) و GitLab CI (باستخدام .gitlab-ci.yml) مع اختلافات بسيطة في الصياغة.
المرحلة الأولى: تشغيل الاختبارات على كل Pull Request
هدفنا الأول هو إنه مع كل Pull Request (طلب دمج) جديد بيعمله أي مبرمج، تشتغل اختباراتنا تلقائيًا. لو فشل أي اختبار، GitHub راح يمنع دمج الكود ويعرض إشارة حمراء واضحة.
1. في مشروعك على GitHub، أنشئ مجلد جديد اسمه .github وداخله مجلد آخر اسمه workflows.
2. داخل مجلد workflows، أنشئ ملف جديد باسم ci.yml والصق فيه الكود التالي (هذا المثال يفترض أنك تستخدم مشروع Node.js مع Cypress):
# .github/workflows/ci.yml
name: CI for Automation Tests
# متى يتم تشغيل هذا الـ Workflow
on:
# شغله مع كل Pull Request يستهدف فرع main
pull_request:
branches: [ main ]
# شغله أيضًا مع كل push مباشر على فرع main (بعد الدمج)
push:
branches: [ main ]
jobs:
cypress-run:
name: Run Cypress Tests
runs-on: ubuntu-latest # استخدم أحدث نسخة من Ubuntu
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18' # حدد نسخة Node.js
- name: Install Dependencies
run: npm install # تثبيت كل المكتبات من package.json
- name: Run Cypress Tests
run: npm run cypress:run # شغّل الأمر المخصص لتشغيل الاختبارات
# هذا الأمر غالبًا يكون في package.json مثل "cypress run"
نصيحة من أبو عمر: قبل ما تعتمد الـ Pipeline، تأكد إنه أمر تشغيل الاختبارات (
npm run cypress:runفي مثالنا) بيشتغل عندك على جهازك المحلي بدون مشاكل. “اللي بشتغل عندك، لازم يشتغل عند الـ CI server”.
المرحلة الثانية: توليد التقارير وحفظها
لما يفشل اختبار على الـ CI، ما بدنا نضطر نعيد تشغيل كل شي محليًا عشان نعرف شو المشكلة. بدنا تقرير واضح وصور للشاشة (Screenshots) وفيديوهات. هون بيجي دور الـ Artifacts في GitHub Actions.
سنقوم بتعديل ملف ci.yml ليقوم بحفظ مجلد التقارير بعد انتهاء الاختبارات، سواء نجحت أو فشلت.
# ... (نفس الكود السابق)
- name: Run Cypress Tests
# continue-on-error: true يسمح للخطوات التالية بالعمل حتى لو فشلت الاختبارات
# هذا مهم عشان نقدر نحفظ التقارير
continue-on-error: true
run: npm run cypress:run
- name: Upload Test Artifacts
# if: always() تضمن أن هذه الخطوة ستعمل دائمًا
if: always()
uses: actions/upload-artifact@v3
with:
name: cypress-artifacts
path: |
cypress/screenshots
cypress/videos
cypress/reports
# أضف أي مجلدات أخرى تحتوي على تقارير
الآن، بعد كل تشغيل للـ Pipeline، ستجد قسمًا اسمه “Artifacts” في صفحة الـ Workflow على GitHub. يمكنك تحميل الملف المضغوط الذي يحتوي على كل التقارير والصور والفيديوهات لتحليل سبب الفشل بسهولة.
المرحلة الثالثة: تشغيل مجموعات اختبار مختلفة (Smoke vs. Regression)
مش دائمًا بدنا نشغّل كل الاختبارات. مجموعة الاختبارات الكاملة (Regression Suite) ممكن تاخد وقت طويل. على الـ Pull Requests، يمكن يكفينا نشغّل مجموعة اختبارات سريعة (Smoke Suite) تتأكد من الوظائف الأساسية. بينما الـ Regression الكاملة ممكن نشغلها فقط عند الدمج في الفرع الرئيسي أو بشكل مجدول كل ليلة.
يمكننا تحقيق ذلك باستخدام الشروط (if) في ملف الـ Workflow.
# .github/workflows/ci.yml
name: CI for Automation Tests
on:
pull_request:
branches: [ main ]
push:
branches: [ main ]
jobs:
automation-tests:
name: Run Automation Tests
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
# ... (خطوات تثبيت البيئة) ...
- name: Install Dependencies
run: npm install
- name: Run Smoke Tests on PR
# هذا الشرط يعني: "شغّل هذه الخطوة فقط إذا كان الحدث هو pull_request"
if: github.event_name == 'pull_request'
run: npm run test:smoke # افترض أن لديك سكربت مخصص للـ Smoke Tests
- name: Run Full Regression Tests on Main
# هذا الشرط يعني: "شغّل هذه الخطوة فقط إذا كان الحدث هو push على فرع main"
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: npm run test:regression # افترض أن لديك سكربت مخصص للـ Regression Tests
# ... (خطوة حفظ التقارير) ...
حركة احترافية: يمكنك أيضًا تشغيل الـ Regression Suite يدويًا على أي Pull Request عن طريق إضافة تعليق معين أو Label. هذا يتطلب إعدادات متقدمة باستخدام `workflow_dispatch` أو مراقبة التعليقات، ولكنه يعطي مرونة كبيرة للفريق.
نصائح من “الختيار” أبو عمر
- ابدأ بسيطًا ثم تطوّر: لا تحاول بناء الـ Pipeline المثالي من أول يوم. ابدأ بخطوات بسيطة مثل تشغيل كل الاختبارات، ثم أضف التقارير، ثم التقسيم بين Smoke و Regression. التطور التدريجي هو مفتاح النجاح.
- استخدم الحاويات (Docker): لضمان أن بيئة الاختبار على الـ CI مطابقة 100% لبيئة المطور، قم بتشغيل اختباراتك داخل Docker Container. هذا يحل مشاكل لا حصر لها من نوع “بس هي شغالة عندي!”.
- الاختبارات الموازية (Parallelization): إذا كانت مجموعة اختباراتك كبيرة وتستغرق وقتًا طويلاً، معظم أدوات الـ CI (مثل Cypress Dashboard, Playwright) توفر طرقًا لتقسيم الاختبارات وتشغيلها على عدة أجهزة افتراضية بالتوازي. هذا يقلل وقت الانتظار بشكل كبير.
- فشل سريع، فشل واضح (Fail Fast, Fail Clear): تأكد من أن الـ Pipeline يفشل بمجرد كسر أول اختبار حرج. يجب أن يكون اسم الاختبار الفاشل ورسالته واضحين في سجلات الـ CI لتسهيل عملية التصحيح.
- لا تنسَ الإشعارات: اربط الـ Pipeline مع قناة Slack أو Microsoft Teams مخصصة لفريق الجودة. الحصول على إشعار فوري عند فشل الـ build يساعد على حل المشكلة بسرعة.
الخلاصة: الـ Pipeline ليس رفاهية، بل ضرورة 👨💻
بناء CI/CD Pipeline للاختبارات قد يبدو معقدًا في البداية، ولكنه استثمار سيعود عليك وعلى فريقك بفوائد لا تقدر بثمن. هو الفرق بين النوم المتقطع قلقًا على جودة المنتج، والنوم الهادئ وأنت واثق أن لديك شبكة أمان قوية تحمي تطبيقك من الأخطاء.
تذكر قصة ليلة الخميس تلك؛ كلما شعرت أن بناء هذا النظام صعب، تذكر أن تكلفة إصلاح خطأ في بيئة الإنتاج أعلى بـ 100 مرة من تكلفة اكتشافه في مرحلة التطوير. ابدأ اليوم، ولو بخطوة بسيطة، وابنِ ثقافة الجودة في فريقك.
استثمروا في الأتمتة اليوم، عشان تناموا مرتاحين بالليل بكرا. 😉