نظرة عامة على 1000 قدم لكتابة اختبارات السرو # frontend @ twiliosendgrid
نشرت: 2020-10-03في Twilio SendGrid ، قمنا بكتابة المئات من اختبارات Cypress من طرف إلى طرف (E2E) ونواصل كتابة المزيد مع إصدار ميزات جديدة عبر تطبيقات وفرق ويب مختلفة. تغطي هذه الاختبارات المجموعة بأكملها ، للتحقق من أن حالات الاستخدام الأكثر شيوعًا التي يمر بها العميل لا تزال تعمل بعد دفع تغييرات الكود الجديدة في تطبيقاتنا.
إذا كنت ترغب في الرجوع خطوة إلى الوراء أولاً وقراءة المزيد حول كيفية التفكير في اختبار E2E بشكل عام ، فلا تتردد في الاطلاع على منشور المدونة هذا والعودة إلى هذا بمجرد أن تكون جاهزًا. لا يتطلب منشور المدونة هذا أن تكون خبيرًا في اختبارات E2E ، ولكنه يساعد في الوصول إلى الإطار العقلي الصحيح حيث سترى سبب قيامنا بالأشياء بطريقة معينة في اختباراتنا. إذا كنت تبحث عن برنامج تعليمي أكثر خطوة بخطوة يقدم لك اختبارات Cypress ، فنحن نوصي بمراجعة مستندات Cypress . في منشور المدونة هذا ، نفترض أنك ربما تكون قد شاهدت أو كتبت العديد من اختبارات Cypress من قبل وأنك مهتم بمعرفة كيف يكتب الآخرون اختبارات Cypress لتطبيقاتهم الخاصة.
بعد كتابة الكثير من اختبارات Cypress ، ستبدأ في ملاحظة أنك تستخدم وظائف وتأكيدات وأنماط مماثلة في Cypress لإنجاز ما تحتاجه. سنعرض لك الأجزاء والاستراتيجيات الأكثر شيوعًا التي استخدمناها أو فعلناها من قبل مع Cypress لكتابة اختبارات مقابل بيئات منفصلة مثل dev أو staging. نأمل أن تمنحك هذه النظرة العامة التي تبلغ 1000 قدم حول كيفية كتابتنا لاختبارات Cypress أفكارًا لمقارنتها بأفكارك وتساعدك على تحسين الطريقة التي تتعامل بها مع اختبارات Cypress.
الخطوط العريضة:
- جولة حول Cypress API
- التفاعل مع العناصر
- التأكيد على العناصر
- التعامل مع واجهات برمجة التطبيقات والخدمات
- إجراء طلبات HTTP باستخدام cy.request (...)
- إنشاء مكونات إضافية قابلة لإعادة الاستخدام باستخدام cy.task ()
- الاستهزاء بطلبات الشبكة باستخدام cy.server () و cy.route ()
- أوامر مخصصة
- حول كائنات الصفحة
- اختيار عدم تشغيل التعليمات البرمجية من جانب العميل باستخدام window.Cypress
- التعامل مع الإطارات المضمنة
- التوحيد عبر بيئات الاختبار
تقرير إخباري عن API Cypress
لنبدأ بالاطلاع على الأجزاء التي استخدمناها بشكل شائع مع Cypress API.
اختيار العناصر
هناك العديد من الطرق لتحديد عناصر DOM ، ولكن يمكنك إنجاز معظم ما تحتاج إلى القيام به من خلال أوامر Cypress هذه ويمكنك عادةً ربط المزيد من الإجراءات والتأكيدات بعد ذلك.
- الحصول على عناصر بناءً على بعض محددات CSS باستخدام
cy.get(“[data-hook='someSelector']”)
أوcy.find(“.selector”)
. - تحديد عناصر بناءً على بعض النصوص مثل
cy.contains(“someText”)
أو الحصول على عنصر بمُحدد معين يحتوي على بعض النصوص مثلcy.contains(“.selector”, “someText”)
. - الحصول على عنصر رئيسي للنظر "داخل" ، بحيث يتم تحديد نطاق جميع استفساراتك المستقبلية لأطفال الوالدين مثل
cy.get(“.selector”).within(() => { cy.get(“.child”) })
. - العثور على قائمة بالعناصر والبحث في "كل منها" لإجراء المزيد من الاستعلامات والتأكيدات مثل
cy.get(“tr”).each(($tableRow) => { cy.wrap($tableRow).find('td').eq(1).should(“contain”, “someText” })
. - في بعض الأحيان ، قد تكون العناصر خارج عرض الصفحة ، لذلك ستحتاج إلى تمرير العنصر إلى العرض أولاً مثل
cy.get(“.buttonFarBelow”).scrollIntoView()
. - ستحتاج أحيانًا إلى مهلة أطول من مهلة الأمر الافتراضية ، لذا يمكنك اختياريًا إضافة
{ timeout: timeoutInMs }
مثلcy.get(“.someElement”, { timeout: 10000 })
.
التفاعل مع العناصر
هذه هي التفاعلات الأكثر استخدامًا الموجودة في اختبارات السرو. في بعض الأحيان ، ستحتاج إلى إضافة خاصية { force: true }
في استدعاءات الوظائف هذه لتجاوز بعض عمليات التحقق مع العناصر. يحدث هذا غالبًا عندما يتم تغطية عنصر بطريقة ما أو مشتق من مكتبة خارجية لا يمكنك التحكم فيها كثيرًا من حيث كيفية عرض العناصر.
- نحتاج إلى النقر فوق العديد من الأشياء مثل الأزرار الموجودة في النماذج والجداول وما شابه ، لذلك نقوم بأشياء مثل
cy.get(“.button”).click()
. - النماذج موجودة في كل مكان في تطبيقات الويب الخاصة بنا لملء تفاصيل المستخدم وحقول البيانات الأخرى. نكتب في هذه المدخلات باستخدام
cy.get(“input”).type(“somekeyboardtyping”)
وقد نحتاج إلى مسح بعض القيم الافتراضية للمدخلات عن طريق مسحها أولاً مثلcy.get(“input”).clear().type(“somenewinput”)
. هناك أيضًا طرق رائعة لكتابة مفاتيح أخرى مثل{enter}
للمفتاح Enter عندما تفعلcy.get(“input”).type(“text{enter}”)
. - يمكننا التفاعل مع خيارات محددة مثل
cy.get(“select”).select(“value”)
ومربعات الاختيار مثلcy.get(“.checkbox”).check()
.
التأكيد على العناصر
هذه هي التأكيدات النموذجية التي يمكنك استخدامها في اختبارات Cypress لتحديد ما إذا كانت الأشياء موجودة على الصفحة بالمحتوى الصحيح.
- للتحقق مما إذا كانت الأشياء تظهر أم لا على الصفحة ، يمكنك التبديل بين
cy.get(“.selector”).should(“be.visible”)
وcy.get(“.selector”).should(“not.be.visible”)
. - لتحديد ما إذا كانت عناصر DOM موجودة في مكان ما في الترميز ، وإذا كنت لا تهتم بالضرورة بما إذا كانت العناصر مرئية ، يمكنك استخدام
cy.get(“.element”).should(“exist”)
أوcy.get(“.element”).should(“not.exist”)
. - لمعرفة ما إذا كان العنصر يحتوي على بعض النصوص أم لا ، يمكنك الاختيار بين
cy.get(“button”).should(“contain”, “someText”)
وcy.get(“button”).should(“not.contain”, “someText”)
. - للتحقق من تعطيل أو تمكين أحد المدخلات أو الزر ، يمكنك التأكيد على هذا النحو:
cy.get(“button”).should(“be.disabled”)
. - لتأكيد ما إذا كان قد تم التحقق من شيء ما ، يمكنك اختبار مثل
cy.get(“.checkbox”).should(“be.checked”)
. - يمكنك عادةً الاعتماد على المزيد من عمليات التحقق من النص الملموس والرؤية ، ولكن في بعض الأحيان يتعين عليك الاعتماد على عمليات التحقق من الفئة مثل
cy.get(“element”).should(“have.class”, “class-name”)
. هناك طرق أخرى مشابهة لاختبار السمات أيضًا مع.should(“have.attr”, “attribute”)
. - غالبًا ما يكون مفيدًا لك أن تربط التأكيدات ببعضها البعض مثل
cy.get(“div”).should(“be.visible”).and(“contain”, “text”)
.
التعامل مع واجهات برمجة التطبيقات والخدمات
عند التعامل مع واجهات برمجة التطبيقات والخدمات المتعلقة بالبريد الإلكتروني ، يمكنك استخدام cy.request(...)
لعمل طلبات HTTP لنقاط النهاية الخلفية باستخدام رؤوس المصادقة. بديل آخر هو أنه يمكنك إنشاء cy.task(...)
يمكن استدعاؤها من أي ملف مواصفات لتغطية الوظائف الأخرى التي يمكن التعامل معها بشكل أفضل في خادم Node مع مكتبات أخرى مثل الاتصال بصندوق بريد إلكتروني والعثور على مطابقة البريد الإلكتروني أو الحصول على مزيد من التحكم في الردود والاستقصاء عن استدعاءات معينة لواجهة برمجة التطبيقات قبل إعادة بعض القيم للاختبارات لاستخدامها.
إجراء طلبات HTTP باستخدام cy.request (...)
يمكنك استخدام cy.request()
لعمل طلبات HTTP لواجهة برمجة التطبيقات الخلفية لإعداد البيانات أو تفكيكها قبل تشغيل حالات الاختبار. عادةً ما تقوم بتمرير عنوان URL لنقطة النهاية وطريقة HTTP مثل "GET" أو "POST" والعناوين وأحيانًا نص طلب لإرساله إلى واجهة API الخلفية. يمكنك بعد ذلك ربط هذا بـ .then((response) => { })
للوصول إلى استجابة الشبكة من خلال خصائص مثل "الحالة" و "الجسم". يظهر هنا مثال لإجراء مكالمة cy.request()
.
في بعض الأحيان ، قد لا تهتم بما إذا كان طلب cy.request(...)
سيفشل أم لا مع رمز الحالة 4xx أو 5xx أثناء التنظيف قبل إجراء الاختبار. أحد السيناريوهات التي قد تختار فيها تجاهل رمز الحالة الفاشل هو عندما يقدم اختبارك طلب GET للتحقق مما إذا كان العنصر لا يزال موجودًا وقد تم حذفه بالفعل. قد يكون العنصر قد تم تنظيفه بالفعل وسيفشل طلب GET مع رمز الحالة 404 غير موجود. في هذه الحالة ، يمكنك تعيين خيار آخر لـ failOnStatusCode: false
حتى لا تفشل اختبارات Cypress قبل تشغيل خطوات الاختبار.
إنشاء مكونات إضافية قابلة لإعادة الاستخدام باستخدام cy.task ()
عندما نريد المزيد من المرونة والتحكم في وظيفة قابلة لإعادة الاستخدام للتحدث إلى خدمة أخرى مثل مزود البريد الإلكتروني الوارد من خلال خادم Node (سنغطي هذا المثال في منشور مدونة لاحق) ، نود توفير وظائفنا الإضافية و الردود المخصصة لطلبات واجهة برمجة التطبيقات (API) لنا للتسلسل والتطبيق في اختبارات Cypress الخاصة بنا. أو ، نود تشغيل بعض التعليمات البرمجية الأخرى في خادم Node — غالبًا ما نبني cy.task()
له. نقوم بإنشاء وظائف البرنامج المساعد في ملفات الوحدة النمطية واستيرادها في plugins/index.ts
حيث نحدد المكونات الإضافية للمهام بالوسيطات التي نحتاجها لتشغيل الوظائف كما هو موضح أدناه.
يمكن استدعاء هذه المكونات الإضافية باستخدام cy.task(“pluginName”, { ...args })
في أي مكان في ملفات المواصفات الخاصة بك ويمكنك توقع حدوث نفس الوظيفة. بينما ، إذا استخدمت cy.request()
، فستقل قابلية إعادة الاستخدام ما لم تغلف هذه الاستدعاءات في كائنات الصفحة أو الملفات المساعدة ليتم استيرادها في كل مكان.
أحد التحذيرات الأخرى هو أنه نظرًا لأنه من المفترض أن يتم تشغيل رمز مهمة البرنامج المساعد في خادم Node ، فلا يمكنك استدعاء أوامر Cypress المعتادة داخل تلك الوظائف مثل Cypress.env(“apiHost”)
أو cy.getCookie('auth_token')
. يمكنك تمرير أشياء مثل سلسلة رمز المصادقة أو مضيف واجهة برمجة التطبيقات الخلفية إلى كائن وسيطة وظيفة المكون الإضافي بالإضافة إلى الأشياء المطلوبة لهيئة الطلب إذا كان يحتاج إلى التحدث إلى واجهة API الخلفية.
الاستهزاء بطلبات الشبكة باستخدام cy.server () و cy.route ()
بالنسبة لاختبارات Cypress التي تتطلب بيانات يصعب إعادة إنتاجها (مثل الاختلافات في حالات واجهة المستخدم المهمة على الصفحة أو التعامل مع استدعاءات أبطأ لواجهة برمجة التطبيقات) ، فإن إحدى ميزات Cypress التي يجب مراعاتها هي إعاقة طلبات الشبكة. يعمل هذا بشكل جيد مع الطلبات المستندة إلى XmlHttpRequest (XHR) إذا كنت تستخدم Vanilla XMLHttpRequest أو مكتبة axios أو jQuery AJAX. يمكنك بعد ذلك استخدام cy.server()
و cy.route()
للاستماع إلى المسارات لسخرية الاستجابات لأي حالة تريدها. هذا مثال:
هناك حالة استخدام أخرى وهي استخدام cy.server()
و cy.route()
و cy.wait()
معًا للاستماع والانتظار حتى تنتهي طلبات الشبكة قبل تنفيذ الخطوات التالية. عادة ، بعد تحميل صفحة أو القيام بنوع من الإجراءات على الصفحة ، سيشير تلميح مرئي بديهي إلى أن شيئًا ما مكتمل أو جاهز لنا للتأكيد والتصرف بناءً عليه. بالنسبة للحالات التي لا يتوفر فيها مثل هذا الدليل المرئي ، يمكنك الانتظار صراحة حتى تنتهي مكالمة API على هذا النحو.
إحدى المشاكل الكبيرة هي أنك إذا كنت تستخدم الجلب لطلبات الشبكة ، فلن تكون قادرًا على الاستهزاء بطلبات الشبكة أو الانتظار حتى تنتهي بنفس الطريقة. ستحتاج إلى حل بديل لاستبدال window.fetch
العادية باستخدام XHR polyfill والقيام ببعض خطوات الإعداد والتنظيف قبل تشغيل اختباراتك كما هو مسجل في هذه المشكلات . هناك أيضًا خاصية FetchPolyfill experimentalFetchPolyfill
اعتبارًا من Cypress 4.9.0 والتي قد تعمل من أجلك ، ولكن بشكل عام ، ما زلنا نبحث عن طرق أفضل للتعامل مع توقف الشبكة عبر استخدام الجلب واستخدام XHR في تطبيقاتنا دون كسر الأشياء. اعتبارًا من Cypress 5.1.0 ، هناك وظيفة cy.route2()
جديدة واعدة (انظر مستندات Cypress ) لإيقاف الشبكة التجريبية لكل من XHR وطلبات الجلب ، لذلك نخطط لترقية إصدار Cypress الخاص بنا وتجربته لمعرفة ما إذا كان إنه يحل مشكلاتنا.
أوامر مخصصة
على غرار المكتبات مثل WebdriverIO ، يمكنك إنشاء أوامر مخصصة عامة يمكن إعادة استخدامها وتوصيلها عبر ملفات المواصفات الخاصة بك ، مثل أمر مخصص للتعامل مع عمليات تسجيل الدخول من خلال واجهة برمجة التطبيقات قبل تشغيل حالات الاختبار الخاصة بك. بمجرد تطويرها في ملف مثل support/commands.ts
، يمكنك الوصول إلى وظائف مثل cy.customCommand()
أو cy.login()
. كتابة أمر مخصص لتسجيل الدخول يبدو هكذا.
حول كائنات الصفحة
كائن الصفحة عبارة عن غلاف حول المحددات والوظائف لمساعدتك على التفاعل مع الصفحة. لا تحتاج إلى إنشاء كائنات صفحة لكتابة اختباراتك ، ولكن من الجيد التفكير في طرق لتغليف التغييرات على واجهة المستخدم. تريد أن تجعل حياتك أسهل من حيث تجميع الأشياء معًا لتجنب تحديث المحددات والتفاعلات في ملفات متعددة بدلاً من مكان واحد.
يمكنك تحديد فئة "الصفحة" الأساسية بوظائف مشتركة مثل open()
لفئات الصفحات الموروثة للمشاركة والتمديد منها. تحدد فئات الصفحة المشتقة وظائف getter الخاصة بها للمحددات والوظائف المساعدة الأخرى أثناء إعادة استخدام وظائف الفئات الأساسية من خلال استدعاءات مثل super.open()
كما هو موضح هنا.
اختيار عدم تشغيل التعليمات البرمجية من جانب العميل باستخدام window.Cypress
عندما اختبرنا التدفقات باستخدام ملفات التنزيل التلقائي مثل ملف CSV ، فغالبًا ما تؤدي التنزيلات إلى كسر اختبارات Cypress الخاصة بنا عن طريق تجميد التشغيل التجريبي. كحل وسط ، أردنا بشكل أساسي اختبار ما إذا كان المستخدم يمكنه الوصول إلى حالة النجاح المناسبة للتنزيل وعدم تنزيل الملف فعليًا في window.Cypress
التجريبي عن طريق إضافة نافذة.
أثناء تشغيل اختبار Cypress ، ستكون هناك نافذة. تمت إضافة خاصية window.Cypress
إلى المتصفح. في التعليمات البرمجية من جانب العميل ، يمكنك اختيار التحقق من عدم وجود خاصية Cypress في كائن النافذة ، ثم إجراء التنزيل كالمعتاد. ولكن ، إذا تم تشغيله في اختبار Cypress ، فلا تقم بالفعل بتنزيل الملف. لقد استفدنا أيضًا من التحقق من خاصية window.Cypress
A / B قيد التشغيل في تطبيق الويب الخاص بنا. لم نرغب في إضافة المزيد من التقلبات والسلوك غير الحتمي من تجارب A / B التي من المحتمل أن تعرض تجارب مختلفة لمستخدمي الاختبار لدينا ، لذلك تحققنا أولاً من أن الخاصية غير موجودة قبل تشغيل منطق التجربة كما هو موضح أدناه.
التعامل مع الإطارات المضمنة
قد يكون التعامل مع الإطارات المضمنة أمرًا صعبًا مع Cypress حيث لا يوجد دعم مضمّن لإطار iframe. هناك [مشكلة] قيد التشغيل ( https://github.com/cypress-io/cypress/issues/136 ) مليئة بالحلول للتعامل مع إطارات iframe الفردية وإطارات iframe المتداخلة ، والتي قد تعمل أو لا تعمل بناءً على الإصدار الحالي من Cypress أو إطار iframe الذي تنوي التفاعل معه. بالنسبة لحالة الاستخدام الخاصة بنا ، احتجنا إلى طريقة للتعامل مع إطارات iframe للفوترة من Zuora في بيئتنا المرحلية للتحقق من تدفقات ترقية واجهة برمجة تطبيقات البريد الإلكتروني وحملات التسويق. تتضمن اختباراتنا ملء عينة من معلومات الفوترة قبل إكمال الترقية إلى عرض جديد في تطبيقنا.
أنشأنا أمرًا cy.iframe(iframeSelector)
لتغليف التعامل مع إطارات iframe. سيؤدي تمرير المحدد إلى iframe إلى فحص محتويات جسم iframe حتى لا يصبح فارغًا ، ثم يعود محتويات الجسم مرة أخرى ليتم ربطه بمزيد من أوامر Cypress كما هو موضح أدناه:
عند العمل باستخدام TypeScript ، يمكنك كتابة أمر iframe المخصص مثل هذا في ملف index.d.ts
الخاص بك:
لإنجاز جزء الفوترة في اختباراتنا ، استخدمنا الأمر iframe المخصص للحصول على محتويات جسم Zuora iframe ثم حددنا العناصر داخل iframe وقمنا بتغيير قيمها مباشرةً. لقد واجهنا سابقًا مشكلات في استخدام cy.find(...).type(...)
والبدائل الأخرى التي لا تعمل ، ولكن لحسن الحظ وجدنا حلًا بديلًا عن طريق تغيير قيم المدخلات والاختيار مباشرة باستخدام أمر الاستدعاء ، مثل cy.get(selector).invoke('val', 'some value')
. ستحتاج أيضًا إلى ”chromeWebSecurity”: false
في ملف التكوين cypress.json
للسماح لك بتجاوز أي أخطاء عبر الأصل. يتم توفير عينة مقتطف من استخدامه مع محددات الحشو أدناه:
التوحيد عبر بيئات الاختبار
بعد كتابة الاختبارات باستخدام Cypress باستخدام التأكيدات والوظائف والأساليب الأكثر شيوعًا التي تم تسليط الضوء عليها سابقًا ، يمكننا إجراء الاختبارات وجعلها تمر في بيئة واحدة. هذه خطوة أولى رائعة ، لكن لدينا بيئات متعددة لنشر كود جديد واختبار التغييرات التي أجريناها. لكل بيئة مجموعتها الخاصة من قواعد البيانات والخوادم والمستخدمين ، ولكن يجب كتابة اختبارات Cypress الخاصة بنا مرة واحدة فقط للعمل بنفس الخطوات العامة.
من أجل إجراء اختبارات Cypress على بيئات اختبار متعددة مثل التطوير والاختبار والتشغيل المرحلي قبل أن ننشر تغييراتنا في النهاية على الإنتاج ، نحتاج إلى الاستفادة من قدرة Cypress على إضافة متغيرات البيئة وتغيير قيم التكوين لدعم حالات الاستخدام هذه.
لإجراء اختباراتك في بيئات مختلفة للواجهة الأمامية :
ستحتاج إلى تغيير قيمة "baseUrl" كما يتم الوصول إليها من خلال Cypress.config(“baseUrl”)
لمطابقة عناوين URL مثل https://staging.app.com أو https://testing.app.com . يؤدي هذا إلى تغيير عنوان URL الأساسي لجميع cy.visit(...)
لإلحاق مساراتهم بها. هناك عدة طرق لتعيين هذا مثل إعداد CYPRESS_BASE_URL=<frontend_url>
قبل تشغيل أمر Cypress أو إعداد --config baseUrl=<frontend_url>
.
لإجراء اختباراتك على بيئات خلفية مختلفة :
تحتاج إلى معرفة اسم مضيف واجهة برمجة التطبيقات مثل https://staging.api.com أو https://testing.api.com لتعيينه في متغير بيئة مثل "apiHost" ويمكن الوصول إليه من خلال مكالمات مثل Cypress.env(“apiHost”)
. سيتم استخدام هذه cy.request(...)
لإجراء طلبات HTTP لمسارات معينة مثل "<apiHost> / بعض / نقطة النهاية" أو تمريرها إلى استدعاءات وظائف cy.task(...)
كوسيطة أخرى خاصية معرفة الخلفية التي يجب ضربها. ستحتاج أيضًا هذه الاستدعاءات المصادق عليها إلى معرفة رمز المصادقة الذي من المرجح أن تخزنه في localStorage أو ملف تعريف ارتباط من خلال cy.getCookie(“auth_token”)
. تأكد من تمرير رمز المصادقة هذا في النهاية كجزء من رأس "التفويض" أو من خلال بعض الوسائل الأخرى كجزء من طلبك. هناك العديد من الطرق لتعيين متغيرات البيئة هذه مثل مباشرة في ملف cypress.json
أو في خيارات سطر الأوامر --env
حيث يمكنك الرجوع إليها في وثائق Cypress .
للتعامل مع تسجيل الدخول إلى مستخدمين مختلفين أو استخدام بيانات وصفية مختلفة:
الآن بعد أن عرفت كيفية التعامل مع عناوين URL متعددة للواجهة الأمامية ومضيفي واجهة برمجة التطبيقات الخلفية ، كيف يمكنك التعامل مع تسجيل الدخول إلى مستخدمين مختلفين؟ كيف تستخدم البيانات الوصفية المتنوعة بناءً على البيئة ، مثل الأشياء المتعلقة بالمجالات ومفاتيح واجهة برمجة التطبيقات والموارد الأخرى التي من المحتمل أن تكون فريدة عبر بيئات الاختبار؟
لنبدأ بإنشاء متغير بيئة آخر يسمى "testEnv" مع القيم المحتملة لـ "الاختبار" و "التدريج" حتى تتمكن من استخدام هذا كطريقة لمعرفة مستخدمي البيئة والبيانات الوصفية التي سيتم تطبيقها في الاختبار. باستخدام متغير البيئة "testEnv" ، يمكنك التعامل مع هذا بطريقتين.
يمكنك إنشاء ملفات "staging.json" و "testing.json" منفصلة وملفات JSON للبيئة الأخرى ضمن مجلد fixtures
واستيرادها لتستخدمها بناءً على قيمة "testEnv" مثل cy.fixture(`${testEnv}.json`).then(...)
. ومع ذلك ، لا يمكنك كتابة ملفات JSON جيدًا وهناك مجال أكبر بكثير للأخطاء في بناء الجملة وكتابة جميع الخصائص المطلوبة لكل اختبار. تكون ملفات JSON أيضًا أبعد ما تكون عن كود الاختبار ، لذلك سيتعين عليك إدارة ملفين على الأقل عند تحرير الاختبارات. قد تحدث مشكلات صيانة مماثلة إذا تم تعيين جميع بيانات اختبار البيئة في متغيرات البيئة مباشرة في cypress.json
الخاص بك وسيكون هناك الكثير من الإدارة عبر عدد كبير من الاختبارات.
يتمثل الخيار البديل في إنشاء كائن اختبار ثابت داخل ملف المواصفات بخصائص تستند إلى الاختبار أو التدريج لتحميل مستخدم الاختبار والبيانات الوصفية لبيئة معينة. نظرًا لأن هذه كائنات ، يمكنك أيضًا تحديد نوع عام أفضل من TypeScript حول كائنات اختبار التثبيت لجميع ملفات المواصفات الخاصة بك لإعادة استخدامها ولتحديد أنواع البيانات الوصفية. يمكنك الاتصال Cypress.env(“testEnv”)
لمعرفة بيئة الاختبار التي تعمل مقابلها واستخدام هذه القيمة لاستخراج تركيبات اختبار البيئة المقابلة من كائن تركيبات الاختبار الشامل واستخدام هذه القيم في اختبارك. يتم تلخيص الفكرة العامة لكائن تركيبات الاختبار في مقتطف الشفرة أدناه.
يتيح لنا تطبيق قيمة تكوين Cypress "baseUrl" ومتغير بيئة الواجهة الخلفية "apiHost" ومتغير البيئة "testEnv" معًا إجراء اختبارات Cypress التي تعمل ضد بيئات متعددة دون إضافة شروط متعددة أو تدفقات منطقية منفصلة كما هو موضح أدناه.
لنعد خطوة إلى الوراء لنرى كيف يمكنك حتى إنشاء أوامر Cypress الخاصة بك للتشغيل خلال npm. يمكن تطبيق مفاهيم مماثلة على الغزل و Makefile والنصوص الأخرى التي قد تستخدمها لتطبيقك. قد ترغب في تحديد أشكال مختلفة من الأمرين "فتح" و "تشغيل" لمحاذاة Cypress "فتح" واجهة المستخدم الرسومية و "تشغيل" في وضع بدون رأس مقابل بيئات الواجهة الأمامية والخلفية المختلفة في package.json
. يمكنك أيضًا إعداد ملفات JSON متعددة لتهيئة كل بيئة ، ولكن للتبسيط ، سترى الأوامر مع الخيارات والقيم المضمنة.
ستلاحظ في البرامج النصية package.json
أن الواجهة الأمامية "baseUrl" تتراوح من "http: // localhost: 9001" عند بدء تشغيل تطبيقك محليًا إلى عنوان URL للتطبيق المنشور مثل " https://staging.app. كوم ". يمكنك تعيين متغيري "apiHost" و "testEnv" للواجهة الخلفية للمساعدة في تقديم الطلبات إلى نقطة نهاية الواجهة الخلفية وتحميل كائن اختبار معين. يمكنك أيضًا إنشاء أوامر "cicd" خاصة عندما تحتاج إلى تشغيل اختباراتك في حاوية Docker باستخدام مفتاح التسجيل.
بعض الوجبات السريعة
عندما يتعلق الأمر بتحديد العناصر ، والتفاعل مع العناصر ، والتأكيد على العناصر الموجودة على الصفحة ، يمكنك الوصول إلى أبعد من ذلك بكثير من خلال كتابة العديد من اختبارات Cypress مع قائمة صغيرة من أوامر Cypress مثل cy.get()
، cy.contains()
، .type()
.click()
، .type ()، .should .should('be.visible')
.
هناك أيضًا طرق لإجراء طلبات HTTP لواجهة برمجة تطبيقات خلفية باستخدام cy.request()
، وتشغيل رمز عشوائي في خادم Node باستخدام cy.task()
، وإيقاف طلبات الشبكة باستخدام cy.server()
و cy.route()
. يمكنك أيضًا إنشاء أمر مخصص خاص بك مثل cy.login()
لمساعدتك في تسجيل الدخول إلى مستخدم من خلال واجهة برمجة التطبيقات. تساعد كل هذه الأشياء في إعادة تعيين المستخدم إلى نقطة البداية المناسبة قبل إجراء الاختبارات. قم بلف هذه المحددات والوظائف معًا في ملف وقمت بإنشاء كائنات صفحة قابلة لإعادة الاستخدام لاستخدامها في المواصفات الخاصة بك.
لمساعدتك في كتابة الاختبارات التي تجتاز أكثر من بيئة ، استفد من متغيرات البيئة والكائنات التي تحتوي على بيانات وصفية خاصة بالبيئة.
سيساعدك هذا في تشغيل مجموعات مختلفة من المستخدمين بموارد بيانات منفصلة في مواصفات Cypress الخاصة بك. أوامر Cypress npm المنفصلة مثل npm run cypress:open:staging
in your package.json
ستحمِّل قيم متغيرات البيئة المناسبة وتُجري اختبارات البيئة التي اخترتها للتشغيل مقابلها.
هذا يختتم نظرة عامة على ألف قدم لكتابة اختبارات السرو. نأمل أن يكون هذا قد زودك بأمثلة وأنماط عملية لتطبيقها وتحسينها في اختبارات السرو الخاصة بك.
هل أنت مهتم بمعرفة المزيد عن اختبارات السرو؟ تحقق من الموارد التالية:
- ما يجب مراعاته عند كتابة اختبارات E2E
- TypeScript كل الأشياء في اختبارات السرو الخاصة بك
- التعامل مع تدفقات البريد الإلكتروني في اختبارات السرو
- أفكار لتكوين وتنظيم وتوحيد اختبارات السرو الخاصة بك
- دمج اختبارات السرو مع Docker و Buildkite و CICD