Shift Left Testing — ليش نقلنا الاختبار من الآخر للأول
بدأنا بأتمتة E2E على الـ Staging: بطيئة، Flaky، وتشغيلها باليد. الـ Shift Left غيّر المعادلة كلها — كيف صار، وشو المهارات اللي بيطلبها منك.
أول ما إجت الأتمتة، حطّينا الاختبارات في آخر السلسلة: التطوير يخلص، ينزل على الـ Staging، وبعدين نشغّل الاختبارات.
واشتغلت — لكن معها إجت مجموعة أوجاع كل واحد اشتغل بهذاك الوقت بيعرفها. الـ Shift Left هو الحل اللي طلع من هذه الأوجاع بالذات.
كيف بدأت أتمتة الاختبار
الصورة كانت هيك تقريباً عند الجميع، ولسا هيك في كثير شركات ودول لليوم:
- Selenium مع Java — الثنائي الأشهر بلا منازع
- مشروع منفصل تماماً، بـ Repository لحاله، بعيد عن كود المنتج
- الاختبارات بتدور على بيئة حقيقية زي الـ Staging
- والتشغيل يدوي: المختبِر بيفتح المشروع وبيضغط Run
وكانت نقلة كبيرة فعلاً. لأول مرة صار عنا Regression بيدور بليلة بدل أسبوع. بس مع الوقت، بانت المشاكل.
الأوجاع اللي عاشها الكل
الاختبارات كانت Flaky. بتنجح مرة وبتفشل مرة، وبنفس الكود. أحياناً السبب البيئة نفسها — الخدمة بطيئة أو راجعة غلط — وأحياناً الاختبار نفسه مكتوب بشكل هش.
بيانات الاختبار كانت كابوس. بدك مستخدم بحالة معيّنة، وطلب بوضع معيّن. وبالشركات الكبيرة هذه لحالها كانت معركة: من بيعمل المستخدمين؟ ومن بينضّفهم بعدين؟ وشو بيصير لما حدا ثاني يستعمل نفس المستخدم بنفس الوقت؟
التشغيل ضل يدوي، والصيانة قبل كل تشغيل. كل تغيير بالواجهة بيكسّر Locators، فقبل ما تشغّل لازم تروح تصلّح.
كل شي كان E2E. ما في مستويات — أي فحص، مهما كان صغير، بيمرق عبر النظام كله.
وبالنهاية: أعِد التشغيل لحد ما ينجح. والأسوأ إنه بعد كل هذا، بتضل تفحص شوية مسارات باليد لأنه في اختبارات ما زبطت بالتشغيل.
إجا الـ Shift Left
الفكرة ببساطة: بدل ما تفحص بالآخر، انزل بالفحص لتحت وللأول — على مستوى الوحدة (Unit) والتكامل (Integration)، وقت ما الخطأ لسا رخيص وسهل تلاقيه.
حتى هذا يصير، طلعت أدوات وممارسات غيّرت شكل الشغل:
افصل الواجهة عن الـ Backend
بدل ما تفحص الواجهة وهي موصولة بكل الخدمات الحقيقية، بتفحصها مقابل Mock Server بيرجّع الردود اللي إنت بدك ياها. النتيجة الجانبية كانت الأهم: صار ممكن تكتب هذه الاختبارات بنفس لغة الواجهة، وبنفس الـ Repository تبعها.
هذه النقطة لحالها حلّت نص المشكلة. الاختبار صار يعيش جنب الكود اللي بيفحصه، فأي تغيير بيكسر الاختبار بيبان بنفس الـ Pull Request — مش بعد أسبوع بمشروع ثاني.
وافصل الـ Backend كمان
نفس المنطق بالضبط: تفحص الـ Backend لحاله، مع قاعدة بيانات مؤقتة بالذاكرة بتتولد وقت التشغيل وبتنمسح بعده، وبيانات بتزرعها إنت (Seeding) بدل ما تستنجد بمستخدمين جاهزين على بيئة مشتركة.
وهيك اختفى سؤال «من بيعمل مستخدمين الاختبار؟» — إنت بتعملهم، بكل تشغيلة، ومن الصفر.
وهون ولد الـ CI/CD
لما صار كل شي بمكان واحد — الكود والاختبارات والـ Mocks — صار ممكن على أي جهاز تشغّل السلسلة كلها: تنصب التطبيق، تعمل Mock لكل شي خارجي بيحتاجه، وتشغّل الاختبارات.
بدك مستخدمين؟ اعملهم Mock. بدك رد معيّن من خدمة؟ اعمله Mock.
وهذا اللي خلّى الاختبارات:
- مستقرة — ما في بيئة مشتركة حدا ثاني بيعبث فيها
- سريعة — ثواني بدل ساعات
- وأهم شي: بتدور لحالها على الـ Pipeline، على كل Pull Request، بلا ما حدا يضغط زر
شكل الهرم بعد الـ Shift Left
القاعدة العملية: ٩٠٪ من تغطيتك على مستوى الوحدة والتكامل، و١٠٪ فقط E2E — ومحصورة بأهم المسارات: تسجيل الدخول، الشراء، الدفع. المسارات اللي لو وقعت، وقع المنتج معها.
شو بيطلب منك الـ Shift Left كمختبِر
هذا مش تغيير بالأدوات بس — هو تغيير بالمهارات:
| المهارة | ليش بتحتاجها |
|---|---|
| الـ Mocking وخوادم الـ Mock | كل الفكرة قايمة عليها: تعزل اللي بتفحصه عن اللي مش بتفحصه |
| Docker | الأداة اللي انفجر استعمالها بهذا العصر — بتخليك تشغّل أي تطبيق على أي جهاز بنفس الشكل بالضبط |
| تصميم الاختبار | تعرف شو بينفحص على أي مستوى، وتقاوم إغراء إنك تفحص كل شي E2E |
| الـ Synthetic Transactions | اختبارات بتدور على الـ Production نفسه لأهم المسارات |
النقطة الأخيرة تستاهل وقفة. الـ Synthetic Transactions اختبارات صغيرة بتدور على البيئة الحية كل كم دقيقة وبتنفّذ مسار حرج — مثلاً: سجّل دخول، ضيف منتج للسلة، ابدأ الدفع. ولما يفشل واحد فيها، هذا إنذار للفريق كله إنه في مشكلة حقيقية على الـ Production بتحتاج تدخّل فوري — مش تذكرة تنحط بالـ Backlog.
وهيك بيصير عندك طرفين مغطّيين: قبل ما ينزل الكود، وبعد ما ينزل.
مثال صغير بيوضّح الفكرة كلها
خلينا نقول في خلل بحساب الخصم: لما تكون قيمة الطلب صفر، بيطلع الخصم رقم سالب.
بالطريقة القديمة: الخلل بيوصل للـ Staging، وبتمسكه باختبار E2E بعد أسبوع. الاختبار بيقولك «صفحة الدفع بتعرض رقم غلط» — وبس. بعدها لازم حدا يفتح الـ Logs، ويتتبّع الطلب، ويوصل للخدمة المسؤولة، ويلاقي الدالة. نص يوم على الأقل، وبين كذا شخص.
بالـ Shift Left: اختبار وحدة على دالة الخصم بيفشل خلال ثانيتين، على جهاز المطوّر، قبل ما الكود يوصل حتى للـ Pull Request. ورسالة الفشل بتقولك اسم الدالة والقيمة المتوقعة والقيمة اللي رجعت.
نفس الخلل بالضبط. الفرق وين مسكته، وهذا الفرق بيتضاعف كل ما نزلت أعمق بالسلسلة.
بالنهاية
الـ Shift Left مش إنك تفحص بدري وخلص. هو إنك تنقل الفحص لأرخص مكان ممكن تلاقي فيه الخطأ. الخطأ اللي بتمسكه باختبار وحدة بيكلّفك دقايق؛ نفس الخطأ لما يوصل للـ Production بيكلّفك اجتماعات وتذاكر واعتذارات.
ولاحظ نمط بيتكرر: كل نقلة بتاريخ الاختبار — من اليدوي للأتمتة، ومن الأتمتة للـ Shift Left — ما ألغت المختبِر، بس رفعت سقف المهارة المطلوبة منه. اللي تعلّم الـ Mocking والـ Docker وتصميم الاختبار وقت ما طلعوا، صار هو اللي بيصمّم النظام كله اليوم.
والسقف رح يرتفع مرة ثانية هسا. بس هذه قصة مقال ثاني.
