ننشر الأتمتة في بضع ساعات: TypeScript ، منقلة ، ياسمين

مرحبا يا هبر!

اسمي فيتالي كوتوف ، أفعل الكثير من اختبارات التشغيل الآلي وأحبها. شاركت مؤخرًا في مشروع لتكوين الأتمتة من البداية على مكدس TypeScript + Protractor + Jasmine. بالنسبة لي ، كانت هذه المجموعة الجديدة وقد بحثت عن المعلومات الضرورية على الإنترنت.

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

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

بالمناسبة ، كان لدي بالفعل مقال مماثل: "نحن ننشر الأتمتة في بضع ساعات: PHPUnit ، السيلينيوم ، الملحن" .



مهمة


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

في هذه المقالة ، لن نفكر في إيجابيات وسلبيات مشاريع AngularJS. بضع كلمات فقط حول ميزات هذه المشاريع من حيث كتابة اختبارات e2e لهم.

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

بالنسبة إلى الويب ، يتم استخدام CSS و Xpath بشكل شائع. في بعض الأحيان ، إذا كان هناك عنصر بمعرف فريد على الصفحة ، يمكنك البحث به. ومع ذلك ، يبدو لي أن WebDriver ما زال يحول هذا المعرف إلى محدد موقع CSS في النهاية ويعمل بالفعل معه.

إذا نظرنا إلى تعليمات HTML البرمجية لبعض مشاريع AngularJS ، فسنرى الكثير من السمات للعناصر غير الموجودة في HTML الكلاسيكية:



الرمز مأخوذ من صفحة المنقلة التجريبية .

يتم استخدام كافة السمات التي تبدأ بـ ng- * بواسطة AngularJS للعمل مع واجهة المستخدم. يتمثل الموقف النموذجي إلى حد ما في عدم وجود عناصر أخرى غير سمات التحكم هذه ، مما يعقد عملية تجميع محددات الجودة.

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

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

ما هو ما


بادئ ذي بدء ، دعونا نتعرف على سبب الحاجة إلى كل مكون من مكونات مجموعتنا.

المنقلة هو إطار اختبار يعتمد على WebDriverJS. هو الذي سيطلق متصفحاتنا ، ويجعلها تفتح الصفحات اللازمة وتتفاعل مع العناصر الضرورية.

تم تصميم هذا الإطار خصيصًا لمشاريع AngularJS. يوفر طرقًا إضافية لتحديد المواقع:

element(by.model('first')); element(by.binding('latest')); element(by.repeater('some')); 

يمكن الاطلاع على قائمة كاملة على الصفحة اليدوية .

تعمل هذه الطرق على تبسيط إنشاء ودعم محددات المواقع في المشروع. ومع ذلك ، يجب أن نفهم أنه "تحت الغطاء" ، يتم تحويل كل هذا في أي حال إلى CSS. الحقيقة هي أن بروتوكول W3C ، الذي يستند إليه التفاعل في WebDriver ، لا يمكنه العمل إلا مع مجموعة محدودة من المواقع. يمكن الاطلاع على هذه القائمة على w3.org .

TypeScript هي لغة برمجة تم إنشاؤها بواسطة Microsoft. يختلف TypeScript عن JavaScript في قدرته على كتابة المتغيرات ، ودعم استخدام الفئات الكاملة ، والقدرة على توصيل الوحدات النمطية.

تتم ترجمة رمز TS المكتوب للعمل مع محرك V8 إلى رمز JS ، والذي يتم تنفيذه بالفعل. أثناء هذا التحول ، يتم التحقق من الكود للتأكد من توافقه. على سبيل المثال ، لا يتم "ترجمة" إذا تم ، بدلاً من int ، تمرير سلسلة بشكل صريح إلى الوظيفة في مكان ما.

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

أدناه نحن ننظر إلى قدراتها.

التجميع وإعداد المشروع


حسنًا ، قررنا مجموعة من الأطر ، فلنقم الآن بتجميع هذا الأمر برمته.

للعمل مع الكود ، اخترت Visual Studio Code من Microsoft. على الرغم من أن العديد منهم يكتبون في WebStorm أو حتى Intellij Idea من JetBrains.

لقد قمت بالفعل بتثبيت NodeJS (v11.6.0) و NPM (6.9.0). إذا لم يكن لديك مشكلة ، فهذه ليست مشكلة ؛ فتثبيتها ليس صعبًا. يتم وصف كل شيء بتفاصيل كافية على الموقع الرسمي .

يمكن استخدام الغزل بدلاً من NPM ، رغم أن هذا ليس مهمًا لمشروع صغير.

في IDE لدينا نحن بصدد إنشاء مشروع جديد. نقوم بإنشاء package.json في جذر المشروع - وفيه سنصف جميع الحزم التي نحتاجها للمشروع.

يمكنك إنشائه باستخدام الأمر npm init . أو يمكنك ببساطة نسخ المحتويات إلى ملف.

في البداية ، يبدو package.json كالتالي:

 { "name": "protractor", "dependencies": { "@types/node": "^10.5.2", "@types/jasmine": "^3.3.12", "protractor": "^5.4.2", "typescript": "^3.4.1" } } 

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

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

TypeScript والتكوين الخاص به


لتثبيت TypeScript ، نحتاج إلى npm:

 npm install -g typescript 

تأكد من تثبيته:

 $ tsc -v Version 3.4.1 

يبدو أن كل شيء في محله.

الآن نحن بحاجة إلى إنشاء تكوين للعمل مع TS. يجب أن يكون أيضًا في جذر المشروع وأن يُطلق عليه tsconfig.json

محتوياته ستكون مثل هذا:

 { "compilerOptions": { "lib": ["es6"], "strict": true, "outDir" : "output_js", "types" : ["jasmine", "node"] }, "exclude": [ "node_modules/*" ] } 

باختصار ، حددنا ما يلي في هذا التكوين:

  • في أي دليل لوضع كود JS النهائي (في حالتنا يكون output_js)
  • تمكين الوضع الصارم
  • مبينة مع الأطر التي نعمل عليها
  • استبعدت node_modules من التجميع

TS لديه مجموعة كبيرة من الإعدادات. هذه كافية لمشروعنا. يمكنك معرفة المزيد في typescriptlang.org .

الآن ، لنرى كيف يعمل أمر tsc ، والذي سيحول كود TS إلى كود JS. للقيام بذلك ، قم بإنشاء ملف check_tsc.ts بسيط بالمحتويات التالية:

 saySomething("Hello, world!"); function saySomething(message: string) { console.log(message); } 

ثم قم بتنفيذ الأمر tsc (لهذا عليك أن تكون داخل دليل المشروع).

سنرى أن لدينا دليل output_js وملف js مشابه بالمحتويات التالية ظهر بداخله:

 "use strict"; saySomething("Hello, world!"); function saySomething(message) { console.log(message); } 

يمكن بالفعل تشغيل هذا الملف باستخدام الأمر node:

 $ node output_js/check_tsc.js Hello, world! 

لذلك ، كتبنا أول برنامج من نوع TypeScipt ، تهانينا. دعنا نكتب الاختبارات الآن. :)

التكوين منقلة


لمنقلة نحن بحاجة أيضا إلى التكوين. لكنه لن يكون في شكل json ، ولكن في شكل ملف ts. دعنا نسميها config.ts وكتابة التعليمات البرمجية التالية هناك:

 import { Config } from "protractor"; export const config: Config = { seleniumAddress: "http://127.0.0.1:4444/wd/hub", SELENIUM_PROMISE_MANAGER: false, capabilities: { browserName: "chrome", /*chromeOptions: { args: [ "--headless", "--window-size=800,600" ] }*/ }, specs: [ "Tests/*Test.js", ] }; 

في هذا الملف حددنا ما يلي:

أولاً ، المسار إلى خادم سيلينيوم قيد التشغيل. إنه سهل التشغيل ، تحتاج فقط إلى تنزيل ملف jar Standalone Server وبرامج التشغيل الضرورية (على سبيل المثال ، برنامج التشغيل chrome لمتصفح Chrome ). بعد ذلك ، اكتب الأمر التالي:

 java -jar -Dwebdriver.chrome.driver=/path/to/chromedriver /path/to/selenium-server-standalone.jar 

نتيجة لذلك ، يجب أن نرى الاستنتاج التالي:

 23:52:41.691 INFO [GridLauncherV3.launch] - Selenium build info: version: '3.11.0', revision: 'e59cfb3' 23:52:41.693 INFO [GridLauncherV3$1.launch] - Launching a standalone Selenium Server on port 4444 2019-05-02 23:52:41.860:INFO::main: Logging initialized @555ms to org.seleniumhq.jetty9.util.log.StdErrLog 23:52:42.149 INFO [SeleniumServer.boot] - Welcome to Selenium for Workgroups.... 23:52:42.149 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444 

المنفذ 4444 افتراضي. يمكن تعيينه باستخدام المعلمة -port أو من خلال معلمة التكوين "seleniumArgs" => "-port".

إذا كنت تريد أسهل وأسرع: يمكنك تنزيل webdriver - package package npm.

ثم قم بإدارة الخادم باستخدام أوامر البدء والإيقاف وما إلى ذلك. لا يوجد فرق كبير ، فأنا معتاد على العمل مع ملف jar. :)

ثانياً ، لقد أوضحنا أننا لا نريد استخدام مدير الوعد. المزيد عن هذا في وقت لاحق.

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

رابعا ، حددنا قناعًا للمواصفات (الاختبارات). كل ما يكمن في مجلد الاختبارات وينتهي بـ Test.js. لماذا في شبيبة ، وليس نهاية الخبر؟ هذا لأنه في النهاية ، ستعمل Node على وجه التحديد مع ملفات JS ، وليس مع ملفات TS. من المهم عدم الخلط ، خاصة في بداية العمل.

الآن قم بإنشاء مجلد الاختبارات واكتب الاختبار الأول. سوف يفعل ما يلي:

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

إليك الكود الذي حصلت عليه:

 import { browser, by, element, protractor } from "protractor"; describe('Search', () => { it('Open google and find a text', async () => { //       let EC = protractor.ExpectedConditions; //    AngularJS await browser.waitForAngularEnabled(false); //   Google await browser.get('https://www.google.com/'); //    css = input[role='combobox'] let input_button = element(by.css("input[role='combobox']")); //     ( presenceOf) await browser.wait(EC.presenceOf(input_button), 5000); //     “protractor” await input_button.sendKeys("protractor"); //      css let submit_button = element(by.css(".FPdoLc input[type='submit'][name='btnK']")); //      ( ,     input-,   ) await browser.wait(EC.presenceOf(submit_button), 5000); //     await submit_button.click(); // ,  URL    'protractor' await browser.wait(EC.urlContains('protractor'), 5000); }); }); 

في التعليمات البرمجية ، نرى أن كل شيء يبدأ بوظيفة description (). لقد أتت إلينا من إطار الياسمين. هذا هو غلاف للسيناريو لدينا. بداخله ، قد تكون هناك وظائف قبل كل () وقبل كل () لإجراء أي تلاعب قبل كل الاختبارات وقبل كل اختبار. العديد من الوظائف () هي في الواقع اختباراتنا. في النهاية ، إذا تم تعريفه ، سيتم تنفيذ afterAll () و afterEach () للمعالجة بعد كل اختبار وكل الاختبارات.

لن أتحدث عن كل ميزات ياسمين ، يمكنك أن تقرأ عنها على الموقع الإلكتروني jasmine.imtqy.com

لإجراء الاختبار ، تحتاج أولاً إلى تحويل رمز TS إلى رمز JS ، ثم تشغيله:

 $ tsc $ protractor output_js/config.js 

بدأ اختبارنا - نحن رائعون. :)



إذا لم يبدأ الاختبار ، فإن الأمر يستحق التدقيق:

  • أن الرمز مكتوب بشكل صحيح. بشكل عام ، إذا كانت هناك أخطاء فادحة في التعليمات البرمجية ، فسنلحق بها أثناء الأمر tsc.
  • أن خادم السيلينيوم يعمل. للقيام بذلك ، يمكنك فتح URL http: //127.0.0.1-00-00444/wd/hub - يجب أن يكون هناك واجهة لجلسات السيلينيوم.
  • يبدأ Chrome هذا بشكل طبيعي بالإصدار الذي تم تنزيله من chrome-driver. للقيام بذلك ، على wd / hub / page ، انقر فوق إنشاء جلسة وحدد Chrome. إذا لم يبدأ التشغيل ، فأنت بحاجة إما إلى تحديث Chrome ، أو تنزيل إصدار آخر من chrome-driver.
  • إذا فشل كل هذا ، يمكنك التحقق من أن أمر تثبيت npm قد تم بنجاح.
  • إذا كان كل شيء مكتوبًا بشكل صحيح ، ولكن لا يزال لا شيء يبدأ - حاول google الخطأ. غالبا ما يساعد. :)

البرامج النصية NPM


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

للقيام بذلك ، أضف عنصر البرامج النصية إلى package.json:

 { "name": "protractor", "scripts": { "test": "rm -rf output_js/; tsc; protractor output_js/config.js" }, "dependencies": { "@types/node": "^10.5.2", "@types/jasmine": "^3.3.12", "protractor": "^5.4.2", "typescript": "^3.4.1" } } 

الآن عند إدخال الأمر npm test ، سيحدث ما يلي: سيتم حذف الدليل output_js الذي يحتوي على الكود القديم ، وسيتم إنشاؤه من جديد وسيتم كتابة رمز JS جديد له. وبعد ذلك تبدأ الاختبارات على الفور.

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

قليلا عن الوعد


في النهاية ، سأتحدث قليلاً عن الوعد ، المزامنة / الانتظار وكيف تختلف كتابة الاختبارات في NodeJS عن نفس Java أو Python.

جافا سكريبت هي لغة غير متزامنة. هذا يعني أن الكود لا يتم تنفيذه دائمًا بالترتيب الذي كتب به. يتضمن ذلك طلبات HTTP ، ونتذكر أن الكود يتصل بخادم Selenium Server عبر HTTP.

يوفر الوعد (عادة ما يطلق عليه "الوعود") طريقة ملائمة لتنظيم الشفرة غير المتزامنة. يمكنك قراءة المزيد عنها في learn.javascript.ru .

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

لنلقِ نظرة على مثال. لنفترض أننا نفّذ الكود التالي:

 driver.findElement().getText(); 

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

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

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

هذه هي الطريقة التي يمكننا بها طباعة نص الزر على صفحة Google (لاحظ أنه نظرًا لأن هذا زر ، فإن النص موجود داخل سمة القيمة):

 //   let submit_button = element(by.css(".FPdoLc input[type='submit'][name='btnK']")); //    await browser.wait(EC.presenceOf(submit_button), 5000); //   then()   await submit_button.getAttribute("value").then((text) => { console.log(text); }); 

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

الواجب المنزلي


كواجب منزلي ، أقترح كتابة اختبارات لصفحة مكتوبة في AngularJS: protractor-demo .

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

يؤدي


دعنا نقيم. تمكنا من كتابة الاختبارات التي تعمل على مجموعة من TypeScript + Protractor + Jasmine. لقد تعلمنا كيفية إنشاء مثل هذا المشروع ، وإنشاء التكوينات اللازمة ، وكتبنا الاختبار الأول.

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

ماذا تقرأ ، أن ننظر فيها


منقلة دليل جيد مع أمثلة جافا سكريبت: https://www.protractortest.org/#/tutorial
لدى ياسمين دليل: https://jasmine.imtqy.com/pages/docs_home.html
لدى TypeScipt بداية جيدة: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html

في الوسط ، يوجد مقال جيد باللغة الإنجليزية حول TypeScript + Protractor + Cucumber: https://medium.com/@igniteram/e2e-testing-with-protractor-cucumber-using-typescript-564575814e4a

وفي المستودع الخاص بي ، نشرت الرمز النهائي لما ناقشناه في هذه المقالة: https://github.com/KotovVitaliy/HarbProtractorJasmineJasmine .

على الإنترنت ، يمكنك العثور على أمثلة لمشاريع أكثر تعقيدًا وأكبر على هذه المجموعة.

شكرا لاهتمامكم! :)

Source: https://habr.com/ru/post/ar451522/


All Articles