زر ‘الشراء’ اختفى: كيف أنقذني اختبار التراجع البصري من كارثة صامتة؟

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

اسمحوا لي أن أبدأ بقصة قصيرة حصلت معي قبل فترة، قصة عن ليلة خميس هادئة تحولت إلى درس لا يُنسى في عالم تطوير الواجهات الأمامية. كنا نعمل على تحديث بسيط لواجهة متجر إلكتروني لأحد العملاء. التحديث كان مجرد تعديل في ملفات الـ CSS لتحسين مظهر بعض الأزرار الثانوية في الموقع. الأمور كانت تبدو “تمام التمام”، كل شيء يعمل محليًا، والاختبارات الآلية (Unit Tests) كلها باللون الأخضر.

بكل ثقة، قمتُ بدفع التغييرات (push) وفتحت طلب دمج (Pull Request) قبل أن أستعد لنهاية أسبوع هادئة. ولكن، بعد دقائق قليلة، وصلني إشعار على البريد الإلكتروني… فشل في عملية البناء (Build Failed) على نظام التكامل المستمر (CI/CD). الغريب أن الفشل لم يكن في الاختبارات التي نعرفها، بل في خطوة اسمها “Visual Regression Check”.

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

بعد قليل من التحقيق، اكتشفت أن تعديلاً بسيطًا في ملف CSS مشترك، كان يستهدف أزرارًا أخرى، قد أثر بالخطأ على زر الشراء الرئيسي وأعطاه خاصية opacity: 0 على شاشات معينة. الزر كان لا يزال موجودًا في الـ DOM، واختبارات الوظائف (Functional Tests) كانت ستنجح لو أنها لم تبحث عنه بصريًا، لكنه كان شفافًا… غير مرئي للمستخدم. تخيلوا لو أن هذا التحديث وصل للمستخدمين؟ كارثة صامتة. لا أخطاء في النظام، لا رسائل تحذير، فقط… لا مبيعات.

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

ما هو اختبار التراجع البصري (Visual Regression Testing)؟ يا جماعة الخير، الموضوع أبسط مما بتتخيلوا!

ببساطة، اختبار التراجع البصري هو عملية آلية لمقارنة مظهر واجهة المستخدم الرسومية (UI) قبل وبعد إجراء تغييرات على الكود. فكر فيه كلعبة “أوجد الفروقات” لكن الذي يلعبها هو الحاسوب بدقة متناهية.

الآلية تعمل كالتالي:

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

“اختبار التراجع البصري هو بمثابة شبكة أمان لواجهة المستخدم الخاصة بك. إنه يمسك بالأخطاء التي لا تراها أنواع الاختبارات الأخرى.”

لماذا لا تكفي الاختبارات التقليدية وحدها؟

قد يسأل سائل: “يا أبو عمر، عندنا Unit Tests و E2E Tests، ألا يكفي هذا؟”. الجواب، من الآخر، هو لا. كل نوع من الاختبارات له مجاله، واختبارات التراجع البصري تسد فجوة مهمة جدًا لا تغطيها الاختبارات الأخرى.

  • أخطاء الـ CSS الصامتة: كما حدث في قصتي، تغيير بسيط في ملف CSS مركزي يمكن أن يُحدث فوضى في أماكن غير متوقعة. اختبارات الوحدة (Unit Tests) لن تكتشف هذا أبدًا لأنها لا “ترى” الواجهة.
  • مشاكل التصميم المتجاوب (Responsive Design): قد يبدو موقعك رائعًا على شاشة لابتوب، ولكنه محطم تمامًا على شاشة هاتف بعرض 360 بكسل. يمكن لاختبارات التراجع البصري أن تأخذ لقطات شاشة على مختلف أحجام الشاشات وتكتشف هذه المشاكل.
  • التغييرات غير المقصودة في التصميم: أحيانًا، تحديث مكتبة خارجية أو مكون مشترك قد يغير حجم خط، أو لون، أو تباعد العناصر بشكل طفيف. هذه التغييرات قد لا “تكسر” الوظائف، لكنها تؤثر على تجربة المستخدم وتناسق العلامة التجارية.
  • التحقق من المحتوى المرئي: هل الأيقونة الصحيحة تظهر؟ هل الصورة تم تحميلها؟ هذه أمور بصرية بحتة.

كيف نبدأ؟ أدوات وتقنيات عملية

الحمد لله، اليوم توجد العديد من الأدوات الرائعة التي تجعل تطبيق اختبار التراجع البصري سهلاً ومباشرًا. بعضها خدمات مدفوعة مثل Percy و Applitools، وبعضها مدمج في أطر عمل الاختبارات الحديثة مثل Playwright و Cypress.

سأركز هنا على Playwright، وهي أداة من Microsoft أحبها كثيرًا لقوتها وسهولتها.

مثال عملي باستخدام Playwright: خطوة بخطوة

لنفترض أننا نريد اختبار صفحة منتج والتأكد من أن زر “الشراء” يظهر دائمًا بشكل صحيح.

1. الإعداد والتثبيت

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


# تثبيت Playwright
npm i -D @playwright/test

# تثبيت المتصفحات التي سيعمل عليها (الخطوة الأولى فقط)
npx playwright install

2. كتابة الاختبار الأول

الآن، لنكتب ملف اختبار بسيط. سنسميه product-page.spec.ts.


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

test.describe('صفحة المنتج', () => {
  test('يجب أن تظهر الواجهة بشكل صحيح', async ({ page }) => {
    // 1. اذهب إلى صفحة المنتج
    await page.goto('/product/my-awesome-product');

    // 2. انتظر حتى يتم تحميل كل شيء (اختياري ولكن موصى به)
    await page.waitForLoadState('networkidle');

    // 3. خذ لقطة شاشة للصفحة بأكملها وقارنها
    await expect(page).toHaveScreenshot('product-page.png');
  });

  test('يجب أن يظهر زر الشراء بشكل صحيح', async ({ page }) => {
    // يمكنك أيضًا أخذ لقطة لمكون معين فقط
    await page.goto('/product/my-awesome-product');

    const buyButton = page.locator('#buy-button');

    // خذ لقطة شاشة للزر فقط
    await expect(buyButton).toHaveScreenshot('buy-button.png');
  });
});

3. إنشاء اللقطات المرجعية

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


npx playwright test --update-snapshots

بعد تشغيل هذا الأمر، ستجد مجلدًا جديدًا بجوار ملف الاختبار الخاص بك يحتوي على الصور المرجعية (مثل product-page.png).

4. اكتشاف التغيير!

الآن، اذهب وقم بإجراء تغيير “خاطئ”. مثلاً، غيّر لون خلفية زر الشراء في ملف الـ CSS من الأخضر إلى الأحمر. ثم قم بتشغيل الاختبارات مرة أخرى، ولكن هذه المرة بدون علامة --update-snapshots:


npx playwright test

هنا يحدث السحر ✨. سيفشل الاختبار، وستحصل على رسالة واضحة في الطرفية. الأهم من ذلك، سيقوم Playwright بإنشاء تقرير HTML يمكنك فتحه لرؤية الاختلافات.

ستجد في التقرير ثلاث صور:

  • Expected: الصورة المرجعية (الزر الأخضر).
  • Actual: الصورة الجديدة (الزر الأحمر).
  • Diff: صورة تسلط الضوء على الأجزاء المختلفة فقط.

بهذه الطريقة، يمكنك أن تقرر: هل هذا التغيير مقصود؟ إذا كان كذلك، تقوم بتشغيل --update-snapshots مرة أخرى لقبوله كمرجع جديد. إذا لم يكن مقصودًا، فقد أنقذتك الأداة من نشر خطأ بصري!

نصائح من خبرة أبو عمر: كيف تنجح في تطبيق اختبار التراجع البصري

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

  • ابدأ صغيرًا ومهمًا: لا تحاول تغطية كل صفحة في موقعك من اليوم الأول. ابدأ بالصفحات والمكونات الأكثر أهمية: الصفحة الرئيسية، صفحة المنتج، عملية الدفع، رأس وتذييل الموقع (Header/Footer).
  • تعامل مع المحتوى الديناميكي: ماذا لو كانت صفحتك تعرض تاريخ اليوم أو اسم مستخدم؟ هذه الأمور ستتسبب في فشل الاختبارات دائمًا. الحل هو استخدام “الإخفاء” (Masking). معظم الأدوات تسمح لك بتحديد عناصر معينة لتجاهلها أثناء المقارنة. في Playwright، يبدو الأمر هكذا:
    
    await expect(page).toHaveScreenshot({ 
      mask: [page.locator('.dynamic-date')] 
    });
        
  • اضبط عتبة الحساسية (Threshold): أحيانًا، قد تكون هناك اختلافات طفيفة جدًا (بكسل واحد أو اثنين) بسبب اختلاف أنظمة التشغيل أو كروت الشاشة. يمكنك ضبط “عتبة” للسماح بنسبة صغيرة من الاختلافات لتجنب الفشل الكاذب. استخدم هذا بحذر.
  • التكامل مع الـ CI/CD هو مفتاح النجاح: القوة الحقيقية لهذه الاختبارات تظهر عندما تعمل بشكل آلي مع كل طلب دمج (Pull Request). قم بإعدادها في GitHub Actions, GitLab CI, أو أي نظام تستخدمه. هذا يضمن عدم وصول أي تغيير بصري غير مرغوب فيه إلى الكود الرئيسي.

الخلاصة: العين التي لا تنام 👁️

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

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

أبو عمر

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

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

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

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

آخر المدونات

التوظيف وبناء الهوية التقنية

سيرتي الذاتية عبرت فلتر الـ ATS لكنها فشلت أمام المدير التقني: كيف أعدت بناءها لتتحدث لغة المهندسين؟

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

28 فبراير، 2026 قراءة المزيد
التوسع والأداء العالي والأحمال

خدمة واحدة فاشلة كادت أن تسقط النظام بأكمله: كيف أنقذني نمط ‘قاطع الدائرة’ (Circuit Breaker) من كارثة متتالية؟

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

27 فبراير، 2026 قراءة المزيد
اختبارات الاداء والجودة

لقد ‘هاجمت’ تطبيقي بنفسي عمداً: كيف كشفت لي ‘هندسة الفوضى’ نقاط الضعف التي لم تظهرها الاختبارات التقليدية

أشارككم قصة حقيقية حول إطلاق فاشل كاد أن يدمر سمعتنا، وكيف قادتنا هذه التجربة المريرة إلى تبني "هندسة الفوضى" (Chaos Engineering). اكتشفوا معنا كيف يمكن...

26 فبراير، 2026 قراءة المزيد
التوسع والأداء العالي والأحمال

عاصفة من الطلبات كادت أن تغرق تطبيقي: كيف أنقذتني طوابير الرسائل (Message Queues) من كارثة الجمعة السوداء؟

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

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

تحديث النظام القديم كان كابوساً: كيف ‘خنقت’ المونوليث تدريجياً بنمط Strangler Fig دون توقف الخدمة

أتذكر ذلك اليوم جيداً، يوم أردنا تحديث نظامنا المونوليث الضخم، فتحول الأمر إلى كابوس حقيقي. في هذه المقالة، أشارككم تجربتي كـ "أبو عمر" في استخدام...

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