اختبار شامل مع Joomla! و Cypress - خطواتي الأولى وأفكاري

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

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

بالمناسبة ، أي شخص يريد التحقق من Cypress سيجد هذا النص مكانًا جيدًا للبدء. يمكنك اختبار المشكلات دون الحاجة إلى تثبيت وتهيئة كل شيء بنفسك. في مستودع Github لمشروع Joomla ، كل شيء جاهز للعمل.

مقدمة

"في حين أنه من الصحيح أن الجودة لا يمكن اختبارها ، فمن الواضح أيضًا أنه بدون اختبار من المستحيل تطوير أي شيء ذي جودة." - [جيمس أ. ويتاكر]

قبل أن أصادف Cypress لأول مرة ، لم أكن أتخيل أن الحواجز التي غالبًا ما كانت تعترض طريق الاختبار الخاص بي سيتم تحريكها جانبًا إلى حد ما. لقد قضيت الكثير من الوقت في اختبار البرامج - وقبل ذلك المزيد من الوقت في التعامل مع المشكلات التي نشأت بسبب نقص الاختبارات! الآن أنا مقتنع بأن الاختبارات التي هي:

  • في أقرب وقت ممكن من البرمجة ،
  • تلقائيا،
  • بشكل متكرر - بشكل مثالي بعد تغيير كل برنامج ،

    جلب أكثر من التكلفة. والأكثر من ذلك: يمكن أن يكون الاختبار ممتعًا.

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

من يجب أن يقرأ هذا النص؟

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

بعض النظريات

المثلث السحري

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

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

 

المثلث السحري في إدارة المشروع - إذا تم استثمار المزيد من الأموال في المشروع ، فسيكون لذلك تأثير إيجابي على الجودة أو الوقت.

وبالعكس ، فإن وفورات التكلفة ستجبر الجودة على الانخفاض و / أو تأخير اكتمالها.

المثلث السحري في إدارة المشروع - إذا تم استثمار أموال أقل في المشروع ، فسيكون لذلك تأثير سلبي على الجودة أو الوقت.

الآن يأتي دور السحر: لقد تغلبنا على العلاقة بين الوقت والتكاليف والجودة ، لأنه على المدى الطويل ، يمكن التغلب على هذا في الواقع.

يمكن التغلب على العلاقة بين الوقت والتكاليف والجودة على المدى الطويل.

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

على المدى الطويل ، يمكن بالفعل التغلب على العلاقة بين التكلفة والوقت والجودة.

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

الدين الفني

التكاليف والفوائد

ستجد في الأدبيات إحصائيات مدمرة حول فرص نجاح مشاريع البرمجيات. لم يتغير شيء يذكر في الصورة السلبية التي تم تسجيلها بالفعل في دراسة أجراها AW Feyhl في التسعينيات. هنا ، في تحليل 162 مشروعًا في 50 منظمة ، تم تحديد انحراف التكلفة مقارنة بالتخطيط الأصلي: 70٪ من المشاريع أظهرت انحرافًا في التكلفة بنسبة 50٪ على الأقل! هناك شيء غير صحيح ، لا يمكنك فقط قبول ذلك ، أليس كذلك؟

قد يكون أحد الحلول هو الاستغناء عن تقديرات التكلفة تمامًا واتباع حجة حركة # NoEstimates . وترى هذه الحركة أن تقديرات التكلفة في مشروع برمجي لا معنى لها. يحتوي مشروع البرنامج وفقًا لرأي #NoEstimates دائمًا على الإنتاج من شيء جديد. الجديد لا يمكن مقارنته مع التجارب الموجودة بالفعل وبالتالي لا يمكن التنبؤ بها.

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

دمج اختبار البرامج في سير عملك

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

التكاليف النسبية لاستكشاف الأخطاء وإصلاحها في مراحل المشروع المختلفة

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

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

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

التكامل المستمر (CI)
التكامل المستمر للاختبارات

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

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

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

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

التطوير القائم على الاختبار (TDD)

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

تساعدك اختبارات TDD على كتابة البرنامج بشكل صحيح .

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

إذا مررت بجزء التمرين في نهاية النص ، فيمكنك تجربته. قم أولاً بإنشاء الاختبار ثم اكتب الرمز لـ Joomla Core. ثم أرسل كل شيء معًا كعلاقات عامة على Github. إذا كان الجميع سيفعلون ذلك ، جملة سيكون لها تغطية اختبار مثالية.

التنمية المدفوعة بالسلوك (BDD)

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

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

ماذا أعني بذلك: "اكتب البرنامج الصحيح"؟ يحدث أن يرى المستخدمون الأشياء بشكل مختلف عن المطورين. إن سير العمل لحذف مقالة في جملة مثال. مرارًا وتكرارًا التقيت بالمستخدمين الذين ينقرون على أيقونة الحالة في المهملات وتفاجأ. عادة ما يفترض المستخدم بشكل حدسي أن العنصر قد تم حذفه نهائيًا ، ولكن تم تبديله من المهملات إلى التنشيط. بالنسبة للمطور ، يعد النقر فوق رمز الحالة تغييرًا للحالة ، وتبديلًا. في جميع طرق العرض الأخرى. لماذا يجب أن يكون هذا مختلفًا في سلة المهملات؟ بالنسبة للمطور ، يتم تنفيذ الوظيفة بدون أخطاء. تعمل Joomla بشكل صحيح. ولكن في نظري الوظيفة ليست هي الوظيفة المناسبة في ذلك المكان ، لأن معظم المستخدمين سيصفونها / يطلبونها بشكل مختلف تمامًا .

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

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

قدم مشروع Joomla BDD في مشروع Google Summer of Code . كان من المأمول أن يتمكن المستخدمون الذين ليس لديهم معرفة برمجية من المشاركة بسهولة أكبر باستخدام Gherkin ). لم يتم اتباع النهج باستمرار. في ذلك الوقت ، استخدمت Joomla Codeception باعتباره أداة الاختبار. مع Cypress ، يمكن أيضًا تطوير BDD بطريقة BDD.

تخطيط

أنواع الاختبار
  • اختبارات الوحدة: اختبار الوحدة هو اختبار يختبر وحدات البرنامج الأصغر بشكل مستقل.
  • اختبارات التكامل: اختبار التكامل هو اختبار يختبر تفاعل الوحدات الفردية.
  • اختبارات E2E أو اختبارات القبول: يتحقق اختبار القبول مما إذا كان البرنامج يفي بالمهمة المحددة في البداية.
الاستراتيجيات

إذا كنت ترغب في إضافة وظيفة جديدة في جملة وتأمينها بالاختبارات ، يمكنك المتابعة بطريقتين.

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

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

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

استراتيجيات الاختبار: الاختبار التنازلي والاختبار التصاعدي

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

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

هرم الاختبار بواسطة مايك كوهن

كم عدد الاختبارات التي يجب تنفيذها لأي نوع من الاختبارات؟ يصف هرم الاختبار لـ Mike Cohn مفهومًا لاستخدام اختبارات البرمجيات الآلية. يتكون الهرم من ثلاثة مستويات ، منظمًا وفقًا لتكرار الاستخدام ومدى ملاءمته. ‍

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

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

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

متطلبات

ما هي المعدات التي تحتاجها للعمل في الجزء العملي التالي؟

ما هي المتطلبات التي يجب أن تعمل على الجزء العملي التالي بنشاط؟ ليس عليك تلبية العديد من المتطلبات لتتمكن من العمل على محتويات هذا الدليل. بالطبع ، يجب أن يكون لديك جهاز كمبيوتر. بيئة تطوير مع Git ، يجب تثبيت أو تثبيت NodeJS و Composer وخادم الويب المحلي عليه.

ما هي المعرفة التي يجب أن تكون لديك شخصيا؟

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

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

اعداد

إعداد Cypress مع جملة!

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

خطوات تهيئة البيئة المحلية:

استنساخ المستودع إلى جذر خادم الويب المحلي لديك:

$ git clone https://github.com/joomla/joomla-cms.git

انتقل إلى مجلد joomla-cms:

$ cd joomla-cms

وفقًا لـ Joomla Roadmap ، سيتم إصدار الإصدار الرئيسي التالي 5.0 في أكتوبر 2023. لكي تكون محدثًا ، أستخدم إصدار التطوير هذا هنا.

التغيير إلى الفرع 5.0-dev :

$ git checkout 5.0-dev

قم بتثبيت كل حزم الملحن المطلوبة:

$ composer install

قم بتثبيت جميع حزم npm المطلوبة:

$ npm install

لمزيد من المعلومات والمساعدة حول إعداد محطة العمل الخاصة بك ، راجع مقالة توثيق Joomla "Setting Up Your Workstation for Joomla Development" . بالنسبة إلى Cypress ، توجد معلومات في cypress.io . لكن هذا ليس ضروريًا في هذه المرحلة. يقوم Joomla بإعداد كل شيء من أجلك. تحتاج فقط إلى إعداد بياناتك الفردية عبر ملف التكوين joomla-cms/cypress.config.js.

قم بإعداد بياناتك الفردية. لهذا يمكنك استخدام القالب joomla-cms/cypress.config.dist.jsكتوجيه. في حالتي ، يبدو هذا الملف على النحو التالي:

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  fixturesFolder: 'tests/cypress/fixtures',
  videosFolder: 'tests/cypress/output/videos',
  screenshotsFolder: 'tests/cypress/output/screenshots',
  viewportHeight: 1000,
  viewportWidth: 1200,
  e2e: {
    setupNodeEvents(on, config) {},
    baseUrl: 'http://localhost/joomla-cms',
    specPattern: [
      'tests/cypress/integration/install/*.cy.{js,jsx,ts,tsx}',
      'tests/cypress/integration/administrator/**/*.cy.{js,jsx,ts,tsx}',
      'tests/cypress/integration/module/**/*.cy.{js,jsx,ts,tsx}',
      'tests/cypress/integration/site/**/*.cy.{js,jsx,ts,tsx}'
    ],
    supportFile: 'tests/cypress/support/index.js',
    scrollBehavior: 'center',
    browser: 'firefox',
    screenshotOnRunFailure: true,
    video: false
  },
  env: {
    sitename: 'Joomla CMS Test',
    name: 'admin',
    email: عنوان البريد الإلكتروني هذا محمي من روبوتات السبام. يجب عليك تفعيل الجافاسكربت لرؤيته.',
    username: 'admin',
    password: 'adminadminadmin',
    db_type: 'MySQLi',
    db_host: 'mysql',
    db_name: 'test_joomla',
    db_user: 'root',
    db_password: 'root',
    db_prefix: 'j4_',
  },
})

لقد أضفت الدليل بشكل ملموس tests/cypress/integration/module/**/*.cy.{js,jsx,ts,tsx}إلى specPattern Array ، لأنني أريد حفظ اختبار للوحدات هناك لاحقًا. ثم قمت بتغيير اسم المستخدم وكلمات المرور لأنني أريد أيضًا اختبار التثبيت يدويًا وتذكر العناصر المخصصة ذاتيًا بشكل أفضل. أستخدم حاوية Docker كقاعدة بيانات ، لذلك قمت بتغيير خادم قاعدة البيانات وبيانات الوصول ، وفي النهاية اضطررت إلى تعيين عنوان URL الجذر http://localhost/joomla-cmsلتثبيت Joomla الخاص بي.

استخدم السرو

عبر Webbrowser

اتصل npm run cypress:openعبر CLI في دليل جذر Joomla الخاص بك. بعد وقت قصير ، سيتم فتح تطبيق Cypress. لقد أنشأنا الملف مسبقًا joomla-cms/cypress.config.dist.js. يمكن ملاحظة هذا الاكتشاف من حقيقة أن اختبار E2E تم تحديده على أنه تم تكوينه.

يفتح تطبيق Cypress بعد الاتصال بالرقم 96 ؛ npm تشغيل cypress: open96 ؛.

هنا يمكنك اختيار ما إذا كنت تريد تشغيل اختبارات E2E والمتصفح الذي تريد استخدامه. على سبيل المثال ، اخترت الخيار "بدء الاختبار في Firefox".

اختبارات E2E في تطبيق Cypress: حدد المتصفح الذي تريد استخدامه.

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

مجموعة اختبار Joomla في Firefox عبر تطبيق Cypress.

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

اختبار تثبيت جملة قيد التقدم.

جربه.إذا كنت تستخدم كما db_host: 'localhost',يمكنك اختبار التثبيت وبالتالي تكوين Joomla بشكل صحيح للعمل في الجزء التالي من هذا النص.

إذا كنت ، مثلي ، تستخدم مصدرًا خارجيًا (ليس مضيف lcoalhost ؛ أستخدم حاوية عامل إرساء) لأن db_hostاختبار هذا النوع من التثبيت ليس جاهزًا بعد. في هذه الحالة ، هناك سؤال حول الأمان في روتين التثبيت ، وهو لم يتم النظر فيه بعد في الاختبارات. في هذه الحالة ، قم بتثبيت Joomla يدويًا بالمعلومات التي تم إدخالها في الملف joomla-cms/cypress.config.js. ستستخدم الاختبارات التالية الإعدادات من ملف التكوين هذا ، على سبيل المثال لتسجيل الدخول إلى منطقة إدارة Joomla. وبهذه الطريقة يقوم مطور الاختبار لا داعي للقلق بشأن إدخال بيانات تسجيل الدخول. يتم دائمًا استخدام المستخدم وكلمة المرور المطابقين تلقائيًا من ملف التكوين.

مقطوعة الرأس

افتراضيًا ، cypress runيتم تشغيل جميع الاختبارات بدون رؤوس ، وينفذ الأمر التالي جميع الاختبارات المشفرة بالفعل ويحفظ لقطات الشاشة في الدليل /joomla-cms/tests/cypress/output/screenshotsفي حالة حدوث خطأ. تم تعيين دليل الإخراج في الملف cypress.config.js.

$ npm run cypress:run

أوامر CLI الأخرى

هناك أوامر مفيدة أخرى لم يتم تنفيذها كنصوص في package.jsonمشروع Joomla. أنا أعملها عبر npx [docs.npmjs.com/commands/npx].

تحقق السرو

يتحقق الأمر cypress verifyمن تثبيت Cypress بشكل صحيح ويمكن تشغيله.

$ npx cypress verify

✔  Verified Cypress! /.../.cache/Cypress/12.8.1/Cypress
معلومات السرو

يقوم الأمر cypress infoبإخراج معلومات حول Cypress والبيئة الحالية.

$ npx cypress info
Displaying Cypress info...

Detected 2 browsers installed:

1. Chromium
  - Name: chromium
  - Channel: stable
  - Version: 113.0.5672.126
  - Executable: chromium
  - Profile: /.../snap/chromium/current

2. Firefox
  - Name: firefox
  - Channel: stable
  - Version: 113.0.1
  - Executable: firefox
  - Profile: /.../snap/firefox/current/Cypress/firefox-stable

Note: to run these browsers, pass : to the '--browser' field

Examples:
- cypress run --browser chromium
- cypress run --browser firefox

Learn More: https://on.cypress.io/launching-browsers

Proxy Settings: none detected
Environment Variables: none detected

Application Data: /.../.config/cypress/cy/development
Browser Profiles: /.../.config/cypress/cy/development/browsers
Binary Caches: /.../.cache/Cypress

Cypress Version: 12.8.1 (stable)
System Platform: linux (Ubuntu - 22.04)
System Memory: 4.08 GB free 788 MB
نسخة السرو

يقوم الأمر cypress versionبطباعة نسخة Cypress الثنائية المثبتة ، وإصدار حزمة Cypress ، وإصدار Electron المستخدم لإنشاء Cypress ، وإصدار العقدة المجمعة.

$ npx cypress version
Cypress package version: 12.8.1
Cypress binary version: 12.8.1
Electron version: 21.0.0
Bundled Node version: 16.16.0

توفر وثائق Cypress معلومات أكثر تفصيلاً.

كتابة أول اختبار خاص بك

إذا نجح كل شيء حتى الآن ، فيمكننا البدء في إنشاء اختباراتنا الخاصة.

احصل على نظرة عامة

التعلم من الاختبارات المتقدمة بالفعل

في إصدار تطوير Joomla CMS ، توجد بالفعل اختبارات Cypress ، وهي موجودة في المجلد /tests/System/integration. وسيجد أولئك الذين يحبون التعلم بالقدوة مقدمة مناسبة هنا.

رمز الاستيراد للمهام المتكررة

يعمل مطورو Joomla على مشروع Joomla-cypress NodeJs ، والذي يوفر كود اختبار لحالات الاختبار الشائعة. يتم استيراد هذه أثناء تثبيت إصدار المطور من CMS باستخدام npm installعبر

  • package.jsonوعبر
  • ملف الدعم /tests/System/support/index.js. يتم تعريف ملف الدعم في التكوين cypress.config.js.
// package.json
{
  "name": "joomla",
  "version": "5.0.0",
  "description": "Joomla CMS",
  "license": "GPL-2.0-or-later",
  "repository": {
    "type": "git",
    "url": "https://github.com/joomla/joomla-cms.git"
  },
...
  "devDependencies": {
    ...
    "joomla-cypress": "^0.0.16",
    ...
  }
}

مثال على ذلك هو النقر فوق زر شريط الأدوات. على سبيل المثال ، Cypress.Commands.add('clickToolbarButton', clickToolbarButton)يتسبب في إتاحة الأمر clickToolbarButton()في الاختبارات المخصصة ومن خلال cy.clickToolbarButton('new')نقرة على الزر Newيتم محاكاة الرمز المطلوب لهذا الأمر في الرمز المقلوب أدناه.

// node_modules/joomla-cypress/src/common.js
...
const clickToolbarButton = (button, subselector = null) => {
  cy.log('**Click on a toolbar button**')
  cy.log('Button: ' + button)
  cy.log('Subselector: ' + subselector)

  switch (button.toLowerCase())
  {
    case "new":
      cy.get("#toolbar-new").click()
      break
    case "publish":
      cy.get("#status-group-children-publish").click()
      break
    case "unpublish":
      cy.get("#status-group-children-unpublish").click()
      break
    case "archive":
      cy.get("#status-group-children-archive").click();
      break
    case "check-in":
      cy.get("#status-group-children-checkin").click()
      break
    case "batch":
      cy.get("#status-group-children-batch").click()
      break
    case "rebuild":
      cy.get('#toolbar-refresh button').click()
      break
    case "trash":
      cy.get("#status-group-children-trash").click()
      break
    case "save":
      cy.get("#toolbar-apply").click()
      break
    case "save & close":
      cy.get(".button-save").contains('Save & Close').click()
      break
    case "save & new":
      cy.get("#save-group-children-save-new").click()
      break
    case "cancel":
      cy.get("#toolbar-cancel").click()
      break
    case "options":
      cy.get("#toolbar-options").click()
      break
    case "empty trash":
    case "delete":
      cy.get("#toolbar-delete").click()
      break
    case "feature":
      cy.get("#status-group-children-featured").click()
      break
    case "unfeature":
      cy.get("#status-group-children-unfeatured").click()
      break
    case "action":
      cy.get("#toolbar-status-group").click()
      break
    case "transition":
      cy.get(".button-transition.transition-" + subselector).click()
      break
  }

  cy.log('--Click on a toolbar button--')
}

Cypress.Commands.add('clickToolbarButton', clickToolbarButton)
...

يُظهر الكود التالي مثالًا آخر ، تسجيل الدخول إلى منطقة الإدارة.

// /node_modules/joomla-cypress/src/user.js
...
const doAdministratorLogin = (user, password, useSnapshot = true) => {
  cy.log('**Do administrator login**')
  cy.log('User: ' + user)
  cy.log('Password: ' + password)

  cy.visit('administrator/index.php')
  cy.get('#mod-login-username').type(user)
  cy.get('#mod-login-password').type(password)
  cy.get('#btn-login-submit').click()
  cy.get('h1.page-title').should('contain', 'Home Dashboard')

  cy.log('--Do administrator login--')
}

Cypress.Commands.add('doAdministratorLogin', doAdministratorLogin)

...
المهام المشتركة في البيئة الفردية

/tests/System/supportستجد في الدليل المهام الشائعة في البيئة الفردية. حتى يمكن إعادة استخدامها بسهولة ، يتم استيرادها عبر ملف الدعم. /tests/System/support/index.jsومن الأمثلة على المهام المتكررة بشكل متكرر تسجيل الدخول إلى منطقة الإدارة ، والتي يتم التعامل معها في الملف /tests/System/support/commands.jsباستخدام الوظيفة doAdministratorLogin.

يوضح الكود التالي أيضًا كيفية استخدام المعلومات من cypress.config.jsالتكوين في الاختبارات. Cypress.env('username')يتم تعيين قيمة الخاصية usernameداخل المجموعة env.

أيضا ، يمكننا أن نرى هنا كيفية الكتابة فوق الأوامر. Cypress.Commands.overwrite('doAdministratorLogin' ...),الكتابة فوق الكود الذي رأيناه للتو في الحزمة joomla-cypress. الميزة هي أن المستخدم وكلمة المرور يتم استخدامهما تلقائيًا من التكوين الفردي.

// /tests/System/support/commands.js
...
Cypress.Commands.overwrite('doAdministratorLogin', (originalFn, username, password, useSnapshot = true) => {
  // Ensure there are valid credentials
  const user = username ?? Cypress.env('username');
  const pw = password ?? Cypress.env('password');

  // Do normal login when no snapshot should be used
  if (!useSnapshot) {
    // Clear the session data
    Cypress.session.clearAllSavedSessions();

    // Call the normal function
    return originalFn(user, pw);
  }

  // Do login through the session
  return cy.session([user, pw, 'back'], () => originalFn(user, pw), { cacheAcrossSpecs: true });
});
...

قم بتثبيت ملحق Joomla الخاص

من أجل معرفة كيفية اختبار الكود الخاص بك ، سنقوم بتثبيت مثال بسيط لمكون عبر الواجهة الخلفية لـ Joomla. يمكن تنزيل ملف التثبيت من Codeberg .

قم بتثبيت امتداد Joomla الخاص.

بعد التثبيت ، يمكنك العثور على رابط لعرض مكون Foo في الشريط الجانبي الأيسر من الواجهة الخلفية لـ Joomla.

عرض عنصر المثال في الواجهة الخلفية لـ Joomla.

لدينا الآن بيئة اختبار تم إعدادها ورمزًا للاختبار.

أول اختبار خاص به

خطاف

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

يوفر Cypress عدة أنواع من الخطافات ، بما في ذلك beforeالخطافات afterالتي تعمل قبل أو بعد الاختبارات في مجموعة اختبار ، beforeEachوالخطافات afterEachالتي تعمل قبل أو بعد كل اختبار فردي في المجموعة. يمكن تعريف الخطافات بشكل عام أو داخل كتلة معينة described. يتسبب مثال الكود في الملف tests/System/integration/administrator/components/com_foos/FoosList.cy.jsفي إجراء تسجيل الدخول في الواجهة الخلفية قبل كل اختبار داخل describedالكتلة test com_foos features.

نبدأ الآن بالجزء العملي وننشئ الملف tests/System/integration/administrator/components/com_foos/FoosList.cy.jsبالرمز التالي قبل كتابة أول اختبار إنتاجي. يجب أن يقوم مثالنا الأول بتسجيل الدخول بنجاح إلى الواجهة الخلفية قبل أي اختبار! سنختبر هذا بعد إنشاء الاختبار الأول.

// tests/System/integration/administrator/components/com_foos/FoosList.cy.js

describe('Test com_foos features', () => {
  beforeEach(() => {
    cy.doAdministratorLogin()
  })

})

ملاحظة: يتم تطبيق الخطافات ، التي يتم تنفيذها داخل الملف /tests/System/support/index.js، على كل ملف اختبار في مجموعة الاختبار.

اختبار ناجح

المكون الذي قمنا بتثبيته للاختبار يحتوي على ثلاثة عناصر Astrid، Ninaأولاً Elmar، نختبر ما إذا كانت هذه العناصر قد تم إنشاؤها بنجاح.

// tests/System/integration/administrator/components/com_foos/FoosList.cy.js

describe('Test com_foos features', () => {
  beforeEach(() => {
    cy.doAdministratorLogin()
  })

  it('list view shows items', function () {
    cy.visit('administrator/index.php?option=com_foos')

    cy.get('main').should('contain.text', 'Astrid')
    cy.get('main').should('contain.text', 'Nina')
    cy.get('main').should('contain.text', 'Elmar')

    cy.checkForPhpNoticesOrWarnings()
  })
})

ملاحظة: الوظيفة checkForPhpNoticesOrWarnings()التي تجدها في الملف /node_modules/joomla-cypress/src/support.js.

نحصل على عنصر DOM mainعبر الأمر Cypress get

يجب أن تجد الاختبار الذي أنشأته للتو FooList.cy.jsفي قائمة الاختبارات المتاحة في الشريط الجانبي الأيسر. إذا لم يكن الأمر كذلك ، يرجى إغلاق المتصفح وتشغيله npm run cypress:openمرة أخرى.

Joomla تشغيل الاختبار للتمديد الخاص.

انقر فوق اسم الاختبار لتشغيله. يجب أن ينتهي بنجاح وسترى الرسائل الخضراء.

العرض بعد تشغيل الاختبار بنجاح.

اختبار فاشل

أضف السطر cy.get('main').should('contain.text', 'Sami')إلى ملف الاختبار حتى يفشل التشغيل. لا يوجد عنصر بهذا الاسم. بعد حفظ ملف الاختبار ، يلاحظ Cypress التغيير. بعد كل تغيير ، يقوم Cypress تلقائيًا بإعادة تشغيل جميع الاختبارات في ملف الاختبار.

// tests/System/integration/administrator/components/com_foos/FoosList.cy.js
describe('Test com_foos features', () => {
  beforeEach(() => {
    cy.doAdministratorLogin()
  })

  it('list view shows items', function () {
    cy.visit('administrator/index.php?option=com_foos')

    cy.get('main').should('contain.text', 'Astrid')
    cy.get('main').should('contain.text', 'Nina')
    cy.get('main').should('contain.text', 'Elmar')
    cy.get('main').should('contain.text', 'Sami')

    cy.checkForPhpNoticesOrWarnings()
  })
})

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

العرض بعد فشل الاختبار.

قم بتشغيل اختبار واحد فقط في الملف

يحتوي ملحق العرض التوضيحي الخاص بنا على أكثر من تخطيط واحد. أضف اختبارًا لاختبار تخطيط الحالة الفارغة. نظرًا لأن لدينا الآن اختبارين في هذا الملف ، فإن Cypress ستجري دائمًا كلا الاختبارين في كل مرة نقوم فيها بحفظ الملف. يمكننا استخدام اختبار واحد .only()فقط يتم تنفيذ:

// tests/System/integration/administrator/components/com_foos/FoosList.cy.js

describe('Test com_foos features', () => {
    beforeEach(() => {
        cy.doAdministratorLogin()
    })

    it('list view shows items', function () {
        cy.visit('administrator/index.php?option=com_foos')

        cy.get('main').should('contain.text', 'Astrid')
        cy.get('main').should('contain.text', 'Nina')
        cy.get('main').should('contain.text', 'Elmar')

        cy.checkForPhpNoticesOrWarnings()
    })

    it.only('emptystate layout', function () {
        cy.visit('administrator/index.php?option=com_foos&view=foos&layout=emptystate')
        cy.get('main').should('contain.text', 'No Foo have been created yet.')
    })
})

أثناء التطوير ، هذا مريح للغاية.

سمات الاختبار الخاصة

نحب الآن اختبار الواجهة الأمامية لمكوننا ، ونقوم بذلك في ملف منفصل /tests/System/integration/site/components/com_foos/FooItem.cy.js.

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

سأستخدم data-testالسمة للعناصر ، أولاً أقوم بإضافة السمة data-test="foo-main"إلى كود الإنتاج.

// /components/com_foos/tmpl/foo/default.php

\defined('_JEXEC') or die;
?>
<div data-test="foo-main">
Hello Foos
</div>

ثم أختبر كود الإنتاج من خلال البحث عن السمة [data-test="foo-main"].

// tests/System/integration/site/components/com_foos/FooItem.cy.js
describe('Test com_foo frontend', () => {
  it('Show frondend via query in url', function () {
    cy.visit('index.php?option=com_foos&view=foo')

    cy.get('[data-test="foo-main"]').should('contain.text', 'Hello Foos')

    cy.checkForPhpNoticesOrWarnings()
  })
})
اختبار عنصر القائمة وبعض الأفكار حول الأحداث والانتظار وأفضل الممارسات

أود الآن اختبار إنشاء عنصر قائمة لمكوننا. أفعل ذلك في ملف منفصل /tests/System/integration/administrator/components/com_foos/MenuItem.cy.js. هذا الرمز معقد ويظهر الكثير من الميزات الخاصة.

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

const testMenuItem = {
  'title': 'Test MenuItem',
  'menuitemtype_title': 'COM_FOOS',
  'menuitemtype_entry': 'COM_FOOS_FOO_VIEW_DEFAULT_TITLE'
}

بعد ذلك ترى الكود الكامل للملف MenuItem.cy.js:

// tests/System/integration/administrator/components/com_foos/MenuItem.cy.js

describe('Test menu item', () => {
  beforeEach(() => {
    cy.doAdministratorLogin(Cypress.env('username'), Cypress.env('password'))
  })

  it('creates a new menu item', function () {
    const testMenuItem = {
      'title': 'Test MenuItem',
      'menuitemtype_title': 'COM_FOOS',
      'menuitemtype_entry': 'COM_FOOS_FOO_VIEW_DEFAULT_TITLE'
    }

    cy.visit('administrator/index.php?option=com_menus&view=item&client_id=0&menutype=mainmenu&layout=edit')
    cy.checkForPhpNoticesOrWarnings()
    cy.get('h1.page-title').should('contain', 'Menus: New Item')

    cy.get('#jform_title').clear().type(testMenuItem.title)

    cy.contains('Select').click()
    cy.get('.iframe').iframe('#collapse1-heading').contains(testMenuItem.menuitemtype_title).click()
    cy.get('.iframe').iframe('#collapse1-heading').contains(testMenuItem.menuitemtype_entry).click()

    cy.intercept('index.php?option=com_menus&view=items&menutype=mainmenu').as('item_list')
    cy.clickToolbarButton('Save & Close')
    cy.wait('@item_list')
    cy.get('#system-message-container').contains('Menu item saved.').should('exist')

    // Frontend
    cy.visit('index.php')
    cy.get('.sidebar-right').contains(testMenuItem.title).click()
    cy.get('[data-test="foo-main"]').should('contain.text', 'Hello Foos')
    cy.checkForPhpNoticesOrWarnings()

    // Trash
    cy.visit('administrator/index.php?option=com_menus&view=items&menutype=mainmenu')
    cy.searchForItem(testMenuItem.title)
    cy.checkAllResults()
    cy.clickToolbarButton('Action')
    cy.intercept('index.php?option=com_menus&view=items&menutype=mainmenu').as('item_trash')
    cy.clickToolbarButton('trash')
    cy.wait('@item_trash')
    cy.get('#system-message-container').contains('Menu item trashed.').should('exist')

    // Delete
    cy.visit('administrator/index.php?option=com_menus&view=items&menutype=mainmenu')
    cy.setFilter('published', 'Trashed')
    cy.searchForItem(testMenuItem.title)
    cy.checkAllResults()
    cy.on("window:confirm", (s) => {
      return true;
    });
    cy.intercept('index.php?option=com_menus&view=items&menutype=mainmenu').as('item_delete')
    cy.clickToolbarButton('empty trash');
    cy.wait('@item_delete')
    cy.get('#system-message-container').contains('Menu item deleted.').should('exist')
  })
})
  • في هذا الرمز ، يمكنك رؤية مثال لاختبار شيء ما ثم حذف كل شيء - وبالتالي استعادة الحالة الأولية. وبهذه الطريقة يمكنك تكرار الاختبارات عدة مرات كما تريد. بدون استعادة الحالة الأولية ، سيفشل التشغيل التجريبي الثاني لأن جملة لا يمكن تخزين عنصرين متشابهين.

ملاحظة: يجب أن يكون الاختبار:

  • قابل للتكرار.
  • بعبارات ملموسة ، هذا يعني أنه يجب اختبار مشكلة محدودة ويجب ألا يكون الرمز الخاص بذلك واسعًا جدًا.
  • مستقل عن الاختبارات الأخرى.
  • ويمكنك معرفة كيفية استخدام مسار تم اعتراضه معرّف بـ cy.intercept()[^ docs.cypress.io / api / commands / intercept] كاسم مستعار ، ثم انتظر المسار المحدد كاسم مستعار بـ cy.wait().

عند كتابة اختبارات لمثل هذه التطبيقات ، يميل المرء إلى استخدام قيم عشوائية مثل cy.wait(2000);الأمر cy.wait. المشكلة في هذا النهج هي أنه بينما قد يعمل هذا بشكل جيد في التطوير. ومع ذلك ، فإنه ليس مضمونًا أن يعمل دائمًا. لماذا؟ لأنه يعتمد النظام الأساسي على أشياء يصعب التنبؤ بها ، لذلك من الأفضل دائمًا تحديد ما تنتظره بالضبط.

  • يُظهر الرمز أيضًا كيفية انتظار تنبيه وتأكيده .
cy.on("window:confirm", (s) => {
  return true;
});
  • أخيرًا وليس آخرًا ، يحتوي كود الاختبار على وظائف Cypress build in و Joomla-model التي يمكن إعادة استخدامها من قبل مطوري الإضافات. على سبيل المثال ، cy.setFilter('published', 'Trashed')أو cy.clickToolbarButton('Save & Close')هي وظائف يمكن من خلالها العثور على حلول للاختبارات الفردية بشكل عام والتي يحتاجها مطورو Joomla بشكل خاص في كثير من الأحيان .
المزج بين Async و Sync Code

Cypress commands are asynchronous, that is, they do not return a value, but generate it. When we start Cypress, it does not execute the commands immediately, but reads them serially and queues them. If you mix asynchronous and synchronous code in tests, you may get unexpected results. If you run the following code, you will get an error against expectation. Surely you would also have expected that mainText = $main.text() changes the value mainText. But mainText === 'Initial' is still valid at the end. Why is that? Cypress first executes the synchronous code at the beginning and at the end. Only then it calls the asynchronous part inside then(). That means, the variable mainText is initialized and immediately afterwards it is checked, if it has changed - which of course is not the case.

let mainText = 'Initial';
cy.visit('administrator/index.php?option=com_foos&view=foos&layout=emptystate')
cy.get("main").then(
  ($main) => (mainText = $main.text())
);

if (mainText === 'Initial') {
  throw new Error(`Der Text hat sich nicht geändert. Er lautet: ${mainText}`);
}

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

cy.get('main').then(function(e){
  console.log(e.text())
})
console.log('Cypress Test.')
بذرة وجواسيس

A stubهي طريقة لمحاكاة سلوك الوظيفة التي تعتمد عليها الاختبارات. بدلاً من استدعاء الوظيفة الفعلية ، يستبدل كعب الروتين هذه الوظيفة ويعيد كائنًا محددًا مسبقًا. وعادة ما يتم استخدامه في اختبارات الوحدة ، ولكن يمكن استخدامه أيضًا للنهاية اختبار حتى النهاية.

A spyمشابه لـ stub، ولكن ليس نفس الشيء تمامًا. فهو لا يغير سلوك الوظيفة ، ولكنه يتركها كما هي. إنه يلتقط بعض المعلومات حول كيفية استدعاء الوظيفة. على سبيل المثال ، للتحقق مما إذا كانت الوظيفة تسمى مع المعلمات الصحيحة ، أو لحساب عدد مرات استدعاء الوظيفة.

يوضح المثال التالي تطبيق a spyو a . من خلال إنشاء العنصر وتحديده في الخطوة التالية التي يتم إرجاعها للمكالمة الأولى والثانية. ، التي تراقب دعوة . الآن نختبر أنه في المكالمة الأولى ، يتم رفض حذف الفئة وفي الاستدعاء الثاني يتم تأكيده. عند القيام بذلك ، يضمن أننا يمكن أن نتوقع على وجه اليقين ما هي قيم العودة تم تغليفها . يساعد على ضمان استدعاء الوظيفة فعليًا - وعدد مرات استدعائها.stubconst stub = cy.stub()stubfalsetruecy.on('window:confirm', stub)stubwindow:confirm'cy.spy(win, 'confirm').as('winConfirmSpy')Spy'window:confirm'stub'window:confirm'@winConfirmSpy

// tests/System/integration/administrator/components/com_foos/FoosList.cy.js
...
const stub = cy.stub()

stub.onFirstCall().returns(false)
stub.onSecondCall().returns(true)

cy.on('window:confirm', stub)

cy.window().then(win => {
  cy.spy(win, 'confirm').as('winConfirmSpy')
})

cy.intercept('index.php?option=com_categories&view=categories&extension=com_foos').as('cat_delete')
cy.clickToolbarButton('empty trash');

cy.get('@winConfirmSpy').should('be.calledOnce')
cy.get('main').should('contain.text', testFoo.category)


cy.clickToolbarButton('empty trash');
cy.wait('@cat_delete')

cy.get('@winConfirmSpy').should('be.calledTwice')

cy.get('#system-message-container').contains('Category deleted.').should('exist')
...

إذا كان الأمر يتعلق فقط بتعيين قيمة ثابتة للمكالمة 'window:confirm'، فسيقوم الكود التالي بالمهمة.

cy.on("window:confirm", (s) => {
  return true;
});

خاتمة

في هذه المقالة ، شاهدت النظرية الأساسية والميزات العملية لاختبار E2E باستخدام Cypress. لقد استخدمت تثبيت Joomla لشرح كيفية كتابة اختبارات مختلفة للتأكد من أن مكون Joomla على موقع ويب يعمل كما هو متوقع. لقد أوضحت أيضًا كيفية تخصيص Cypress اختبار Runner في ملف cypress.json وكيفية استخدام أوامر Cypress المخصصة. تم ذلك باستخدام أمثلة سهلة المتابعة.

أتمنى أن تكون قد استمتعت بالجولة عبر Cypress باستخدام Joomla كمثال وأنك تمكنت من أخذ الكثير من المعرفة والإلهام لنفسك.

An online collaborative community manual for Joomla! users, developers or anyone interested in learning more about Joomla! Currently, we have more than 9,000 articles written, maintained, and translated by our Joomla! community members. 

يرجى ملاحظة أن هذا الموقع يستخدم نظام ترجمة آلي للمساعدة في الترجمة للغات المختلفة ، ونحن نعتذر عن أي خطأ أو خطأ يمكن أن يظهر في النصوص المختلفة.