من عدّل على الـ CSS؟: كيف أنقذتنا اختبارات الانحدار البصري من كوابيس الواجهة الأمامية

يا جماعة الخير، السلام عليكم ورحمة الله.

بتذكر مرة، قبل كم سنة، كنا شغالين على مشروع ضخم لعميل مهم جداً. المشروع كان منصة تجارة إلكترونية، وكنا على وشك الإطلاق الرسمي. الليلة اللي قبل الإطلاق، زي ما بتعرفوا، بتكون ليلة “ساعة الصفر”. الأدرينالين عالي، والكل متوتر، والقهوة شغالة ٢٤ ساعة.

قبل موعد الإطلاق بساعتين، وصلني إيميل من مديرة التسويق، العنوان “URGENT: Landing Page is BROKEN!!!”. قلبي وقع بين رجليي، الله وكيلكم. فتحت الرابط، وإذ بالصفحة الرئيسية اللي كانت مبارح زي العروس، صايرة شكلها غريب. الزر الرئيسي للشراء (Call to Action) نصه طاير خارج الشاشة على الموبايل، وصورة المنتج الرئيسي عليها خط أبيض غريب. الدنيا قايمة وقاعدة، والكل بسأل: “مين آخر واحد عمل push؟ مين لعب بالـ CSS؟”.

بعد تحقيق سريع، اكتشفنا إنه واحد من الشباب الطيبة، مبرمج جديد معنا، كان شغال على تعديل بسيط جداً في الـ `footer` (تذييل الصفحة). تغيير سطر واحد في ملف CSS مشترك، عشان يحل مشكلة صغيرة في صفحة “اتصل بنا”. ما كان إله أي علاقة بالصفحة الرئيسية. لكن هذا التغيير البسيط، بسبب الـ “وراثة” (inheritance) في CSS، عمل تأثير الفراشة (Butterfly Effect) وضرب تصميم الصفحة الرئيسية في مقتل.

هذيك الليلة، واحنا بنصلح المشكلة على أعصابنا، أخذت قرار: “هذا الوضع لازم يتغير. مش معقول نضل عايشين على أعصابنا مع كل تعديل CSS”. ومن هنا، بدأت رحلتنا مع عالم “اختبارات الانحدار البصري”.

ما هي اختبارات الانحدار البصري (Visual Regression Testing)؟

باختصار شديد، هي عملية أتمتة للتحقق من أن واجهات المستخدم الرسومية (GUIs) لا تزال تبدو صحيحة بعد أي تغييرات في الكود. بدل ما تخلي واحد من فريقك (أو أنت شخصياً) يفتح كل صفحات الموقع بعد كل تعديل عشان يتأكد إنه ما في شي “خرب”، بنخلي الكمبيوتر يعمل هاي الشغلة عنا.

الفكرة ببساطة… زي لعبة “أوجد الفروقات”

تخيلها زي لعبة “أوجد الفروقات” اللي كنا نلعبها واحنا صغار. العملية بتمشي بالخطوات التالية:

  1. الصورة المرجعية (Baseline): في المرة الأولى اللي بتشغل فيها الاختبار على صفحة معينة، الأداة بتاخد “لقطة شاشة” (Screenshot) للصفحة أو للمكون (Component) وبتحفظها كصورة مرجعية. هاي هي النسخة “الأصلية” اللي ما فيها أخطاء.
  2. الصورة الجديدة (New Screenshot): بعد ما تعمل أي تعديلات على الكود (مثلاً، تعديل CSS، إضافة زر، تحديث نسخة مكتبة)، بتشغل الاختبار مرة ثانية. الأداة بتاخد لقطة شاشة جديدة لنفس الصفحة.
  3. المقارنة (Comparison): الأداة بتقارن بكسل بكسل بين الصورة الجديدة والصورة المرجعية.
  4. التقرير (Report):
    • إذا الصورتين متطابقات تماماً، الاختبار بنجح ✅. امورك تمام.
    • إذا في أي اختلاف، حتى لو بكسل واحد، الاختبار بفشل ❌. والأداة بتعطيك تقرير حلو ومرتب، بصورة ثالثة بتوضحلك بالضبط وين الاختلافات (عادة بتلونها باللون الأحمر).

وقتها، أنت كمطور بتقرر: هل هذا الاختلاف مقصود ومتوقع (لأني فعلاً غيرت التصميم)؟ إذا نعم، بتكبس زر “تحديث الصورة المرجعية” وبتصير الصورة الجديدة هي الأساس للمرات الجاي. أو هل هذا الاختلاف هو “خربطة” غير مقصودة (زي ما صار معنا)؟ إذا نعم، بترجع بتصلح الكود تبعك وبترتاح إنه الاختبار كشفلك المشكلة قبل ما توصل للمستخدم أو للعميل.

ليش وجعة الراس هاي كلها؟ (الفوائد الحقيقية)

ممكن واحد يسأل: “طيب يا أبو عمر، كل هاي اللفة عشان شوية بكسلات؟”. الجواب هو إنه الموضوع أكبر من مجرد بكسلات. الفوائد بتغير طريقة شغلك كلها.

الثقة بالنفس (Confidence)

أكبر فائدة. بتصير قادر تعمل `refactor` لملفات CSS ضخمة ومعقدة وأنت مرتاح البال. بتصير قادر تحدث مكتبات الـ UI بدون ما تخاف إنها تكسرلك الدنيا. بتكبس زر `Deploy` وأنت واثق إنه الواجهات اللي بتهمك ما تأثرت.

الكفاءة والسرعة (Efficiency and Speed)

بدل ما تضيع وقت فريق الـ QA أو وقتك في فحص يدوي ممل وعرضة للخطأ، الأتمتة بتعمل الشغل عنك في ثواني أو دقائق. هذا بيعني دورات تطوير أسرع وتوفير في الموارد.

اكتشاف الأخطاء الخفية

العين البشرية بتغفل عن أشياء كثير. ممكن تغيير بسيط يعمل إزاحة 2 بكسل لليمين، أو يغير درجة لون بشكل طفيف. يمكن ما تلاحظها بعينك، لكن الاختبار الآلي بيكشفها فوراً. هاي الأمور بتتراكم ومع الوقت بتخلي التصميم “مش نظيف”.

توثيق بصري لتطور المشروع

سجلات اختباراتك بتصير زي ألبوم صور لتطور واجهات مشروعك عبر الزمن. بتقدر ترجع وتشوف كيف كان شكل الزر الفلاني قبل 6 أشهر، وهذا بحد ذاته مفيد جداً.

طيب يا أبو عمر، كيف نبدأ؟

الحمد لله، السوق مليان أدوات ممتازة، منها المجاني ومنها المدفوع. الخيار بيعتمد على حجم فريقك، ميزانيتك، وطبيعة مشروعك.

أشهر الأدوات في الساحة

  • Storybook: إذا كنت بتستخدم نظام المكونات (Component-Based System) زي React أو Vue أو Angular، فـ Storybook أداة لا غنى عنها. ومع إضافات مثل `storybook-visual-test` أو التكامل مع خدمات مثل Chromatic، بصير عندك نظام اختبار بصري على مستوى المكونات، وهذا دقيق جداً وقوي.
  • Playwright / Cypress: هاي الأدوات أساساً لاختبارات الـ End-to-End، لكن كلاهما عندهم قدرات ممتازة لأخذ لقطات الشاشة والمقارنة. Playwright بالذات، عنده ميزة `toHaveScreenshot` مدمجة وسهلة جداً للاستخدام.
  • Percy / Applitools / Chromatic: هاي خدمات مدفوعة (SaaS) متخصصة في الاختبار البصري. بتوفرلك واجهات إدارة متقدمة، تكامل سهل مع CI/CD، وميزات ذكاء اصطناعي لتجميع الأخطاء المتشابهة وتقليل الضجيج. Chromatic مملوك من نفس جماعة Storybook والتكامل بينهم ممتاز. Percy من BrowserStack وهو خيار قوي جداً.
  • BackstopJS: خيار مجاني ومفتوح المصدر. أنت بتستضيفه وبتديره بنفسك. بيحتاج شوية إعدادات، لكنه قوي جداً وبيعطيك تحكم كامل. مناسب للشركات اللي بدها حل داخلي.

مثال عملي باستخدام Playwright

لأنه بسيط ومباشر، خلينا نشوف مثال سريع باستخدام Playwright. بعد ما تنصب Playwright في مشروعك، كتابة اختبار بصري بسيطة جداً:


import { test, expect } from '@playwright/test';

test.describe('Homepage Visual Tests', () => {

  test('should look the same as the baseline', async ({ page }) => {
    // 1. اذهب إلى الصفحة المطلوبة
    await page.goto('https://your-website.com');

    // 2. انتظر حتى يتم تحميل عنصر معين لضمان اكتمال الصفحة
    await page.waitForSelector('.main-hero-section');

    // 3. خذ لقطة شاشة وقارنها بالمرجعية
    // اسم الملف 'homepage-desktop.png' هو المعرّف الخاص بهذا الاختبار
    await expect(page).toHaveScreenshot('homepage-desktop.png', { 
        fullPage: true, // خذ لقطة للصفحة كاملة
        maxDiffPixels: 100 // اسمح بوجود اختلاف بسيط يصل لـ 100 بكسل
    });
  });

});

شرح الكود:

  • أول مرة تشغل الاختبار: Playwright ما رح يلاقي ملف اسمه `homepage-desktop.png` كمرجع، فبياخد لقطة شاشة وبيحفظها في مجلد خاص بالـ snapshots. الاختبار بينجح.
  • المرات التالية: Playwright بياخد لقطة شاشة جديدة، وبيقارنها بالصورة المرجعية المحفوظة. إذا في اختلاف أكبر من `maxDiffPixels` اللي حددناه، الاختبار بفشل، وبتلاقي في تقرير الاختبار 3 صور: الصورة المرجعية، الصورة الجديدة، وصورة ثالثة بتوضح الفروقات باللون الأحمر.

نصائح من عمك أبو عمر (من قلب التجربة)

الشغل النظيف بغلب الورشات الكبيرة. استثمر في أدواتك وعملياتك، بترتاح لقدام.

1. ابدأ صغيراً (Start Small)

لا تحاول تختبر كل صفحات موقعك من أول يوم. رح تغرق في المشاكل والتنبيهات الكاذبة. ابدأ بالصفحات أو المكونات الحرجة: الصفحة الرئيسية، صفحة المنتج، سلة الشراء، الأزرار الرئيسية، الهيدر والفوتر. بعدين توسع شوي شوي.

2. التكامل مع الـ CI/CD هو سر النجاح

لا تترك تشغيل الاختبارات كخطوة يدوية. اربطها مع نظام الـ CI/CD (زي GitHub Actions, GitLab CI, Jenkins). خلي الاختبارات تشتغل أوتوماتيكياً مع كل Pull Request. هيك، بتقدر تشوف نتيجة الاختبار البصري قبل ما تدمج الكود الجديد، وبتمنع وصول “الخربطات” للفرع الرئيسي أصلاً.

3. تعامل مع المحتوى الديناميكي بذكاء

أكبر عدو للاختبارات البصرية هو المحتوى الديناميكي: التواريخ، أسماء المستخدمين، الإعلانات، العدادات… هاي الأشياء بتتغير مع كل تحميل للصفحة وبتسبب فشل كاذب للاختبارات. الحل؟

  • إخفاء العناصر (Masking): معظم الأدوات بتسمحلك تحدد عناصر معينة عشان “تخفيها” أو تتجاهلها أثناء المقارنة. الأداة بتغطيها بلون ثابت قبل ما تقارن الصور.
  • تثبيت البيانات (Mocking Data): في بيئة الاختبار، استخدم بيانات ثابتة بدل البيانات الحية.

في Playwright مثلاً، يمكنك إخفاء عنصر كالتالي:


await expect(page).toHaveScreenshot('user-profile.png', {
  mask: [page.locator('.dynamic-date-time')],
});

4. لا تكن حساساً جداً (Configure Threshold)

أحياناً، بعض المتصفحات أو كروت الشاشة بتعمل `rendering` مختلف بشكل بسيط جداً (anti-aliasing مثلاً). هذا ممكن يسبب اختلاف بكسل أو اثنين. معظم الأدوات بتسمحلك تحدد “عتبة” (threshold) أو عدد بكسلات مسموح به للاختلاف. استخدمها بحكمة عشان تتجنب التنبيهات الكاذبة، لكن لا ترفعها كثير لدرجة إنها تخفي أخطاء حقيقية.

الخلاصة: شغل نظيف ومريح للراس 🧘‍♂️

الانتقال من الفوضى والصراخ “مين اللي لعب بالـ CSS؟” إلى عملية منظمة ومؤتمتة كان من أفضل القرارات اللي أخذناها في فريقنا. اختبارات الانحدار البصري مش مجرد أداة تقنية، هي تغيير في ثقافة العمل نحو الجودة والثقة.

نعم، في البداية رح تحتاج شوية وقت وجهد عشان تضبطها. لكن العائد على هذا الاستثمار هائل: راحة بال، ثقة أثناء الإطلاق، وفريق سعيد بيركز على الإبداع بدل إطفاء الحرائق.

نصيحتي الأخيرة: لا تنتظروا ليلة إطلاق كارثية زي اللي صارت معنا. ابدأوا اليوم، ولو بخطوة صغيرة. استثمروا في جودة شغلكم… صحتكم النفسية بتشكركم بعدين 😉.

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

ادارة الفرق والتنمية البشرية

المهندس القائد أم المدير؟ كيف أنقذنا أفضل مبرمجينا من جحيم “الترقية العقابية”

قصة حقيقية عن أفضل مبرمجينا الذي كاد أن يغرق في الاجتماعات بعد ترقيته، وكيف أنقذنا موهبته عبر تعريف دور "المهندس القائد" وفصل المسار التقني عن...

26 مايو، 2026 قراءة المزيد
​معمارية البرمجيات

كان كودنا لا يفهم طبيعة عملنا: كيف أنقذنا ‘التصميم الموجه بالمجال’ (DDD) من جحيم ‘ماذا تفعل هذه الدالة؟’

كودنا كان يتحدث لغة لا يفهمها خبراء العمل، مما خلق فوضى عارمة. في هذه المقالة، أشارككم قصة كيف ساعدنا التصميم الموجه بالمجال (DDD) في بناء...

26 مايو، 2026 قراءة المزيد
خوارزميات

كانت دوالنا تعاني من فقدان الذاكرة: كيف أنقذتنا ‘البرمجة الديناميكية’ من جحيم إعادة الحسابات المتكررة؟

في هذه المقالة، يشاركنا أبو عمر، مبرمج فلسطيني خبير، قصة من أرض الواقع عن كيفية ترويض الخوارزميات البطيئة. استكشف معنا مفهوم البرمجة الديناميكية، وتعلم كيف...

26 مايو، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

كان تطبيقنا جميلاً ولكن أعمى: كيف أنقذتنا ‘إمكانية الوصول’ من جحيم استبعاد 15% من المستخدمين؟

أشارككم قصة حقيقية حول كيف اكتشفنا أن تطبيقنا الذي قضينا شهوراً في تلميعه كان يستبعد شريحة ضخمة من المستخدمين. هذه المقالة ليست مجرد درس تقني...

26 مايو، 2026 قراءة المزيد
البودكاست