إضافات Chrome: رحلة العين إلى اختبار تعليق مشغّل الخدمات

ما هو موضوع هذا الطلب؟

يتضمن الانتقال من الإصدار 2 من ملف البيان إلى الإصدار 3 تغييرًا أساسيًا. في الإصدار 2 من بيان الإضافة، كانت الإضافات متوفّرة في صفحة خلفية. كانت صفحات الخلفية تدير عملية التواصل بين الإضافات وصفحات الويب. يستخدم الإصدار 3 من ملف البيان مهام الخدمة بدلاً من ذلك.

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

من نحن؟

eyeo هي شركة مخصّصة لتقديم تبادل متوازن ومستدِم للقيمة على الإنترنت للمستخدمين والمتصفّحات والمعلنين والناشرين. لدينا أكثر من 300 مليون مستخدم على مستوى العالم يستخدمون ميزة فلترة الإعلانات ويسمحون بعرض "الإعلانات المقبولة"، وهو معيار إعلان تم إنشاؤه بشكل مستقل يحدّد ما إذا كان الإعلان مقبولًا وغير مزعج.

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

ما هو المقصود بعملية الخدمة؟

عمال خدمات الإضافات هم معالِج الأحداث المركزي في إضافة المتصفّح. ويتم تشغيلها بشكل مستقل في الخلفية. هذا أمر جيد بشكل عام. يمكننا تنفيذ معظم الإجراءات التي نحتاج إليها في صفحة خلفية في الخدمة الجديدة. ولكن هناك بعض التغييرات مقارنةً بالصفحات التي تعمل في الخلفية:

  • تنتهي مهام الخدمة عند عدم استخدامها. يتطلّب ذلك تثبيت حالات التطبيق بدلاً من الاعتماد على المتغيّرات الشاملة. وهذا يعني أنّه يجب إعداد أي نقاط دخول إلى نظامنا ليتم استدعاؤها قبل بدء تشغيل النظام.
  • يجب إرفاق مستمعي الأحداث قبل انتظار أيّ استدعاءات للوظائف غير المتزامنة. سيظل بإمكان مهام الخدمة المعلّقة تلقّي الأحداث التي اشتركت فيها. إذا لم يتم تسجيل مستمع الحدث في الخطوة الأولى من حلقة الأحداث، لن يتلقّى الحدث إذا كان هذا الحدث قد أيقظ عامل الخدمة.
  • يمكن أن يؤدي إيقاف المعالجة في حالة عدم النشاط إلى إيقاف الموقّتات قبل اكتمالها.

متى يتم تعليق خدمات "العامل في الخدمة"؟

في الإصدار 119 من Chrome، تبيّن لنا أنّه تم تعليق عمال الخدمة:

  • بعد عدم تلقّي أحداث أو الاتصال بواجهات برمجة تطبيقات الإضافات لمدة 30 ثانية
  • لا يحدث ذلك أبدًا إذا كانت أدوات المطوّرين مفتوحة أو كنت تستخدم مكتبة اختبار مستندة إلى ChromeDriver (راجِع طلب الميزة).
  • إذا نقرت على إيقاف في chrome://serviceworker-internals

للحصول على معلومات حديثة، يُرجى الاطّلاع على دورة حياة مشغِّلات الخدمات.

ما هي المشكلة في اختبار هذا الإجراء؟

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

  • لدينا حالة في إضافة الاختبار. عند إيقاف الخدمة، نفقد حالتها وأحداثها المسجّلة. كيف يمكننا الاحتفاظ بالبيانات في عملية الاختبار؟
  • إذا كان من الممكن تعليق خدمات العمال في أي وقت، يجب اختبار عمل جميع الميزات في حال انقطاعها.
  • حتى لو أدخلنا آلية في اختباراتنا تعمل على تعليق مهام الخدمة بشكل عشوائي، لا تتوفّر واجهة برمجة تطبيقات في المتصفّح لإيقافها بسهولة. لقد طلبنا من فريق W3C إضافة هذه الميزة، ولكنّ هذه المحادثة لا تزال جارية.

اختبار تعليق مشغِّل الخدمات

لقد جرّبنا عدة طرق لتعليق الخدمة أثناء الاختبارات:

المنهجية المشاكل المتعلقة بالمنهجية
الانتظار لمدّة عشوائية (مثل 30 ثانية) ويؤدي ذلك إلى بطء الاختبار وعدم موثوقية النتائج، لا سيما عند إجراء اختبارات متعددة. لا يعمل هذا الإجراء عند استخدام WebDriver، لأنّ WebDriver يستخدم واجهة برمجة التطبيقات DevTools API في Chrome، ولا يتم تعليق الخدمة العاملة عندما تكون أدوات مطوري البرامج مفتوحة. حتى إذا كان بإمكاننا تجاوز هذا الخطأ، سيظل علينا التحقّق مما إذا تم تعليق مشغّل الخدمة، ولا تتوفّر لدينا طريقة لإجراء ذلك.
تشغيل حلقة لا تنتهي في مشغّل الخدمة وفقًا للمواصفات، يمكن أن يؤدي ذلك إلى إنهاء الخدمة استنادًا إلى كيفية تنفيذ المتصفّح لهذه الوظيفة. لا يُنهي Chrome مشغّل الخدمة في هذه الحالة، لذا لا يمكننا اختبار السيناريو الذي يتم فيه تعليق مشغّل الخدمة.
تلقّي رسالة في الخدمة العاملة للتحقّق مما إذا تم تعليقها يؤدي إرسال رسالة إلى تنشيط الخدمة العاملة. يمكن استخدام هذا الإجراء للتحقّق مما إذا كان عامل الخدمة في وضع السكون، ولكنّه يُؤدي إلى تقسيم نتائج الاختبارات التي تحتاج إلى إجراء عمليات تحقّق فور تعليق عامل الخدمة.
يمكنك إنهاء عملية الخدمة باستخدام chrome.processes.terminate()‎. يشترك مشغّل الخدمات للإضافة في عملية مع أجزاء أخرى من الإضافة، لذا فإنّ إنهاء هذه العملية باستخدام chrome.process.terminate() أو واجهة المستخدم لإدارة العمليات في Chrome لا يؤدي إلى إنهاء مشغّل الخدمات فحسب، بل يؤدي أيضًا إلى إنهاء أي صفحات للإضافة.

انتهينا من إجراء اختبار يتحقّق من كيفية استجابة الرمز البرمجي لعملية تعليق الخدمة من خلال جعل Selenium WebDriver يفتح chrome://serviceworker-internals/ والنقر على زر "إيقاف" لخدمة worker.

هذا هو الخيار الأفضل حتى الآن، ولكنه ليس مثاليًا لأنّ اختبارات Mocha (التي يتم تشغيلها على صفحة إضافة) لا يمكنها إجراء ذلك بنفسها، لذا عليها التواصل مع برنامج عقدة WebDriver. وهذا يعني أنّه لا يمكن إجراء هذه الاختبارات باستخدام الإضافة فقط، بل يجب تشغيلها باستخدام Selenium WebDriver.

في ما يلي مخطّط بياني يوضّح كيفية تواصلنا مع واجهة برمجة تطبيقات المتصفّح من خلال عمليات مختلفة ومدى تأثّر هذه العمليات بإضافة آلية "تعليق مهام الخدمة".

مخطّط بياني يعرض مسار الاختبار
مسار الاختبار مع تعليق مشغّل الخدمة

في عملية جديدة تعمل على تعليق مهام الخدمة (باللون الأزرق)، أضفنا Selenium WebDriver "للنقر" على تعليق من خلال واجهة المستخدم، ما يؤدي إلى تنفيذ إجراء في واجهة برمجة تطبيقات المتصفّح.

تجدر الإشارة إلى أنّه كان هناك خطأ في Chrome أدّى إلى تعذُّر بدء تشغيل عامل الخدمة مرة أخرى عند إجراء ذلك باستخدام Selenium WebDriver. تم إصلاح هذه المشكلة في الإصدار 116 من Chrome، ولحسن الحظ، هناك أيضًا حل بديل: ضبط Chrome لفتح "أدوات مطوّري البرامج" تلقائيًا في كل علامة تبويب يؤدي إلى بدء الخدمة بشكل صحيح.

هذا هو النهج الذي نتّبعه عند الاختبار على الرغم من أنّه ليس مثاليًا لأنّ النقر على الزر قد لا يكون واجهة برمجة تطبيقات ثابتة ويبدو أنّ فتح "أدوات مطوّري البرامج" (لمتصفّحات الإصدارات القديمة) يؤثر في الأداء.

كيف نغطي الوظيفة بأكملها؟ اختبارات التداخل

بعد أن توصّلنا إلى آلية لاختبار التعليق، كان علينا تحديد كيفية دمجها في مجموعات اختبارات التشغيل الآلي. أجرينا اختباراتنا العادية في بيئة يتم فيها تعليق عامل الخدمة قبل كل تفاعل مع الصفحة في الخلفية، وذلك من خلال WebDriver بالنقر على إيقاف في صفحة chrome://serviceworker-internals/.

نموذج لتنفيذ اختبار التداخل
صورة تعرض الإعداد الحالي للاختبارات

نُجري معظم الاختبارات وليس كلها لأنّ آلية التعليق ليست مستقرة تمامًا، وفي بعض الأحيان تؤدي إلى حدوث مشاكل. بالإضافة إلى ذلك، يستغرق تشغيل جميع حِزم الاختبار في وضع "الفحص العشوائي" وقتًا طويلاً. لذا، بدلاً من تغطية جميع الحالات "المشابهة"، اخترنا المسارات الأكثر أهمية للاختبار في وضع "التشويش". تجدر الإشارة إلى أنّ تشغيل الاختبارات الوظيفية في وضع "التشويش" يعني أنّنا اضطررنا إلى زيادة مهلات الاختبارات لأنّ تعليق مهام الخدمة وإعادة تشغيلها يستغرق وقتًا إضافيًا.

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

ونحن نُطلق على هذه الأنواع من الاختبارات اسم "اختبارات الأخطاء العشوائية". في العادة، يتم إجراء اختبار التداخل من خلال إدخال بيانات غير صالحة في البرنامج والتأكّد من أنّه يستجيب بشكل معقول أو على الأقل لا يتعطّل. في حالتنا، "الإدخال غير الصالح" هو تعليق عامل الخدمة في أي وقت، و "السلوك المعقول" الذي نتوقّعه هو أن تستمر وظيفة فلترة الإعلانات في العمل كما في السابق. هذه ليست إدخالًا غير صالح لأنّ هذا السلوك متوقّع في الإصدار 3 من ملف البيان، ولكن كان هذا الإدخال غير صالح في الإصدار 2 من ملف البيان، لذا يبدو أنّ هذه المصطلحات معقولة.

ملخّص

تُعدّ مهام الخدمة أحد أكبر التغييرات في الإصدار 3 من ملف البيان (بجانب قواعد declarativeNetRequest). قد تتطلّب عملية نقل البيانات إلى الإصدار 3 من ملف البيان إجراء العديد من التغييرات على الرموز البرمجية في إضافات المتصفّح واستخدام طرق جديدة للاختبار. ويتطلّب ذلك أيضًا من مطوّري الإضافات التي تتضمّن حالة دائمة إعداد إضافاتهم للتعامل مع تعليق الخدمة غير المتوقّع بطريقة سلسة.

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

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