اذهب إلى المحتوى

إعداد البيئة للاختبارات الآلية في مشاريع الويب للتوافق مع المتصفحات


Ola Abbas

سنتعلم في هذا المقال كيفية تثبيت بيئة الاختبارات الآلية وإجراء اختباراتك باستخدام نظام Selenium/WebDriver ومكتبة اختبار مثل selenium-webdriver في Node، وسنتعرّف على كيفية دمج بيئة اختبارك المحلية مع الأدوات التجارية مثل الأدوات التي ناقشناها في المقال السابق.

نظام الاختبار Selenium

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

تعتمد كيفية تثبيت واجهة WebDriver واستخدامها على البيئة البرمجية التي تريد استخدامها لكتابة الاختبارات وتشغيلها، كما تحتوي معظم البيئات الشائعة على حزمة أو إطار عمل يثبّت واجهة WebDriver والارتباطات المطلوبة للتواصل معها باستخدام هذه اللغة مثل لغات Java و C#‎ و Ruby و Python و JavaScript (Node)‎ وغيرها.

تتطلب المتصفحات المختلفة مشغّلات Drivers مختلفة للسماح لواجهة WebDriver بالاتصال والتحكم بها، وراجع المنصات التي يدعمها Selenium للحصول على مزيد من المعلومات حول مكان الحصول على مشغّلات المتصفحات.

سنغطّي كتابة وتشغيل اختبارات Selenium باستخدام Node.js التي تُعَدّ سريعةً وسهلة الاستخدام وبيئةً مألوفةً أكثر لمطورِي الواجهة الأمامية.

إعداد Selenium في Node

  1. أعِدّ أولًا مشروع npm جديد كما ناقشنا في قسم إعداد Node و npm في المقال السابق، وسمِّ هذا المشروع باسم مختلف مثل selenium-test.
  2. يجب بعد ذلك تثبيت إطار عمل للسماح بالتعامل مع Selenium ضمن Node، كما سنختار مكتبة selenium-webdriver الرسمية الخاصة بنظام Selenium، فتوثيقها محدثٌ إلى حد ما وتُطبَّق صيانتها جيدًا، وتوجد خيارات أخرى جيدة مثل webdriver.io و nightwatch.js، كما يمكنك تثبيت selenium-webdriver من خلال تشغيل الأمر التالي مع التأكد من أنك ضمن مجلد مشروعك:
npm install selenium-webdriver

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

يجب بعد ذلك تنزيل المشغّلات ذات الصلة لتتمكّن WebDriver من التحكم في المتصفحات التي تريد اختبارها. تُعَد بعض المتصفحات خاصة بنظام التشغيل، لذلك سنلتزم باستخدام فايرفوكس Firefox وكروم Chrome المتوفرَين على جميع أنظمة التشغيل الرئيسية.

  1. نزّل الإصدار الأحدث من المشغّلات GeckoDriver (لمتصفح Firefox) و ChromeDriver.
  2. فك ضغطها في مكان يسهل الانتقال إليه مثل جذر مجلد مستخدمك الرئيسي.
  3. أضِف موقع مشغّل chromedriver و geckodriver إلى المتغير PATH في نظامك، ويجب أن يكون هذا الموقع مسارًا مطلقًا من جذر قرصك الصلب إلى المجلد الذي يحتوي على المشغّلات، فإذا استخدمت جهاز macOS وكان اسم مستخدِمك هو sami ووضعت المشغّلات في جذر المجلد الرئيسي مثلًا، فسيكون المسار ‎/Users/sami.

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

يمكنك ضبط المتغير PATH على نظام macOS ومعظم أنظمة لينكس كما يلي:

  1. إذا لم تستخدِم صدفة bash مثل أنظمة macOS التي يكون فيها الإعداد الافتراضي هو صدفة zsh وليس bash، فبدّل إلى صدفة bash كما يلي:
exec bash
  1. افتح ملف ‎.bash_profile أو ‎.bashrc، فإذا لم تتمكن من رؤية الملفات المخفية، فستحتاج لعرضها.
  2. الصق ما يلي في أسفل الملف (عدّل المسار كما هو على جهازك):
#Add WebDriver browser drivers to PATH

export PATH=$PATH:/Users/sami
  1. احفظ هذا الملف وأغلقه، ثم أعِد تشغيل موجّه الأوامر أو الطرفية لإعادة تطبيق إعداد Bash.
  2. تحقق من وجود مساراتك الجديدة في المتغير PATH من خلال إدخال ما يلي في طرفيتك:
echo $PATH
  1. يجب أن تراه مطبوعًا في الطرفية.

لنجرب اختبارًا سريعًا للتأكد من أن كل شيء يعمل.

أولًا، أنشئ ملفًا جديدًا ضمن مجلد مشروعك بالاسم google_test.js.

ثانيًا، ضع فيه المحتويات التالية ثم احفظه:

const webdriver = require('selenium-webdriver'),
    By = webdriver.By,
    until = webdriver.until;

const driver = new webdriver.Builder()
    .forBrowser('firefox')
    .build();

driver.get('http://www.google.com');

driver.findElement(By.name('q')).sendKeys('webdriver');

driver.sleep(1000).then(function() {
  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
});

driver.findElement(By.name('btnK')).click();

driver.sleep(2000).then(function() {
  driver.getTitle().then(function(title) {
    if(title === 'webdriver - Google Search') {
      console.log('Test passed');
    } else {
      console.log('Test failed');
    }
    driver.quit();
  });
});

ثالثًا، تأكد من أنك ضمن مجلد مشروعك في الطرفية ثم أدخِل الأمر التالي:

node google_test

يجب أن ترى متصفح Firefox يفتح تلقائيًا، ويجب تحميل جوجل تلقائيًا في تبويب المتصفح، وإدخال النص "webdriver" في مربع البحث، وسيُنقَر على زر البحث، ثم ستنتظر بعدها WebDriver لمدة ثانيتين، ثم يجب الوصول إلى عنوان المستند، وإذا كان النص "webdriver - Google Search"، فستُعاد رسالة تعبِّر عن اجتياز الاختبار، ثم ستغلِق WebDriver المتصفحَ Firefox وتتوقف.

اختبار متصفحات متعددة في وقت واحد

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

أولًا، أنشئ ملفًا جديدًا آخر ضمن مجلد مشروعك بالاسم googletestmultiple.js، ولا تتردد في تغيير المراجع إلى بعض المتصفحات الأخرى التي أضفناها أو إزالتها وغير ذلك اعتمادًا على المتصفحات المتاحة للاختبار على نظام تشغيلك، ولكن يجب التأكد من إعداد مشغّلات المتصفحات الصحيحة على نظامك، فإذا أردت معرفة السلسلة النصية المراد استخدامها ضمن التابع ‎.forBrowser()‎ للمتصفحات الأخرى، فراجع صفحة قائمة المتصفحات.

ثانيًا، ضع المحتويات التالية في هذا الملف ثم احفظه:

const webdriver = require('selenium-webdriver'),
    By = webdriver.By,
    until = webdriver.until;

let driver_fx = new webdriver.Builder()
    .forBrowser('firefox')
    .build();

let driver_chr = new webdriver.Builder()
    .forBrowser('chrome')
    .build();

searchTest(driver_fx);
searchTest(driver_chr);

function searchTest(driver) {
  driver.get('http://www.google.com');
  driver.findElement(By.name('q')).sendKeys('webdriver');

 driver.sleep(1000).then(() => {
    driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
  });

  driver.findElement(By.name('btnK')).click();

 driver.sleep(2000).then(() => {
    driver.getTitle().then((title) => {
      if(title === 'webdriver - Google Search') {
        console.log('Test passed');
      } else {
        console.log('Test failed');
      }
      driver.quit();
    });
  });

}

تأكد من أنك ضمن مجلد مشروعك في الطرفية ثم أدخِل الأمر التالي:

node google_test_multiple

إذا استخدمت جهاز ماك Mac وقررت اختبار المتصفح سفاري Safari، فيمكن أن تتلقى رسالة خطأ مثل "Could not create a session: You must enable the 'Allow Remote Automation' option in Safari's Develop menu to control Safari via WebDriver"، فإذا حصلت على هذا الخطأ، فاتبع التعليمات المُعطاة وحاول مرةً أخرى.

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

لنلقِ نظرةً الآن على أساسيات صياغة واجهة WebDriver بمزيد من التفاصيل.

أساسيات صياغة WebDriver

لنلقِ نظرةً على بعض الميزات الرئيسية لصياغة Webdriver، ويمكنك الحصول على مزيد من التفاصيل من خلال الرجوع إلى مرجع واجهة برمجة تطبيقات جافاسكربت selenium-webdriver وتوثيق Selenium الرئيسي الذي يحتوي على أمثلة متعددة مكتوبة بلغات مختلفة للتعلم منها.

بدء اختبار جديد

يجب تضمين الوحدة selenium-webdriver كما يلي لبدء اختبار جديد:

const webdriver = require('selenium-webdriver');
const By = webdriver.By;
const until = webdriver.until;

يجب بعد ذلك إنشاء نسخة جديدة من المشغّل باستخدام الباني new webdriver.Builder()‎، ولكن يجب ربط التابع forBrowser()‎ بها لتحديد المتصفح الذي تريد اختباره باستخدام هذا الباني، والتابع build()‎ لبنائه.

let driver = new webdriver.Builder()
    .forBrowser('firefox')
    .build();

لاحظ أنه يمكن ضبط خيارات إعدادات محددة للمتصفحات المراد اختبارها، إذ يمكنك مثلًا ضبط إصدار معيّن من المتصفح ونظام التشغيل للاختبار ضمن التابع forBrowser()‎ كما يلي:

let driver = new webdriver.Builder()
    .forBrowser('firefox', '46', 'MAC')
    .build();

كما يمكنك ضبط هذه الخيارات باستخدام متغير البيئة كما يلي على سبيل المثال:

SELENIUM_BROWSER=firefox:46:MAC

لننشئ اختبارًا جديدًا من خلال إنشاء ملف جديد بالاسم quick_test.js ضمن مجلد مشروعك لاختبار Selenium وأضِف الشيفرة البرمجية التالية إليه:

const webdriver = require('selenium-webdriver');
const By = webdriver.By;
const until = webdriver.until;

const driver = new webdriver.Builder()
    .forBrowser('firefox')
    .build();

الحصول على الصفحة الذي تريد اختبارها

يمكنك تحميل الصفحة التي تريد اختبارها من خلال استخدام التابع get()‎ مع نسخة المشغّل التي أنشأتها مسبقًا كما يلي:

driver.get('http://www.google.com');

يمكنك استخدام أيّ عنوان URL للإشارة إلى موردك، بما في ذلك العنوان file://‎ لاختبار مستند محلي كما يلي:

driver.get('file:///Users/chrismills/git/learning-area/tools-testing/cross-browser-testing/accessibility/fake-div-buttons.html');

أو كما يلي:

driver.get('http://localhost:8888/fake-div-buttons.html');

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

أضِف السطر التالي في نهاية الملف quick_test.js:

driver.get('https://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html');

التفاعل مع الصفحة

لدينا مستند للاختبار، لذا يجب التفاعل معه بطريقة ما تتضمن تحديد عنصر معيّن أولًا لاختباره، ويمكنك تحديد عناصر واجهة المستخدِم بعدة طرق في WebDriver بما في ذلك استخدام المعرّف ID والصنف Class واسم العنصر وغير ذلك، كما يمكن تحقيق تحديد العنصر الفعلي باستخدام التابع findElement()‎ الذي يقبل تابعَ تحديد بوصفه معاملًا له، إذ يمكن مثلًا تحديد عنصر باستخدام المعرّف كما يلي:

const element = driver.findElement(By.id('myElementId'));

إحدى أكثر الطرق المفيدة للعثور على عنصر باستخدام لغة CSS هي استخدام التابع By.css الذي يسمح بتحديد عنصر باستخدام محدَّد CSS.

أدخِل ما يلي في الجزء السفلي من شيفرة الملف quick_test.js:

const button = driver.findElement(By.css('button:nth-of-type(1)'));

اختبار العنصر

إذا أردت إدخال نص ضمن الزر، فيمكننا استخدام ما يلي ضمن الملف quick_test.js:

button.getText().then((text) => {
  console.log(`Button text is '${text}'`);
});

تأكد من أنك ضمن مجلد المشروع وشغّل الاختبار كما يلي:

node quick_test.js

يجب أن ترى تسمية نص الزر في الطرفية.

احذف إدخال الشيفرة السابقة ثم أضِف السطر التالي عوضًا عنه:

button.click();

شغّل اختبارك مرةً أخرى، إذ سيُنقَر على الزر وستظهر نافذة التنبيه alert()‎ المنبثقة، وسنعلَم بذلك أنّ الزر يعمل على الأقل.

كما يمكنك التفاعل مع النافذة المنبثقة من خلال إضافة ما يلي إلى أسفل الشيفرة البرمجية واختبارها مرةً أخرى:

const alert = driver.switchTo().alert();

alert.getText().then((text) => {
  console.log(`Alert text is '${text}'`);
});

alert.accept();

لنحاول بعد ذلك إدخال نص في أحد عناصر النموذج، لذا أضِف الشيفرة التالية وشغّل اختبارك مرةً أخرى:

const input = driver.findElement(By.id('name'));
input.sendKeys('Filling in my form');

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

driver.sleep(1000).then(() => {
  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
});

انتظار اكتمال شيء ما

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

ضمّن الكتلة التالية في اختبار الملف google_test.js مثلًا:

driver.sleep(2000).then(() => {
  driver.getTitle().then((title) => {
    if(title === 'webdriver - Google Search') {
      console.log('Test passed');
    } else {
      console.log('Test failed');
    }
  });
});

يقبل التابع sleep()‎ قيمةً تحدد وقت الانتظار بالميلي ثانية ويعيد وعدًا يُؤكَّد في نهاية ذلك الوقت وتُنفَّذ الشيفرة البرمجية الموجودة ضمن التابع then()‎، إذ نحصل في هذه الحالة على عنوان الصفحة الحالية باستخدام التابع getTitle()‎ ثم نعيد رسالة نجاح أو فشل اعتمادًا على قيمة هذا العنوان.

كما يمكننا إضافة التابع sleep()‎ إلى اختبار الملف quick_test.js، لذا غلّف آخر سطر من الشيفرة البرمجية ضمن كتلة كما يلي:

driver.sleep(2000).then(() => {
  input.sendKeys('Filling in my form');
  input.getAttribute("value").then((value) => {
    if(value !== '') {
      console.log('Form input editable');
    }
  });
});

ستنتظر واجهة WebDriver الآن لمدة ثانيتين قبل ملء حقل النموذج ثم نختبر مما فيما إذا كانت قيمته مملوءةً -أي ليست فارغةً- باستخدام التابع getAttribute()‎ لاسترداد قيمة السمة value وطباعة رسالة في الطرفية إذا لم تكن فارغةً.

ملاحظة: هناك تابع بالاسم wait()‎ يختبر بطريقة تكرارية شرطًا لفترة زمنية معينة ثم ينفّذ الشيفرة البرمجية، إذ يستخدِم هذا التابع المكتبة until التي تحدِّد الشروط الشائعة للاستخدام مع التابع wait()‎.

إغلاق المشغلات بعد الانتهاء من استخدامها

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

استدعِ هذا التابع على نسخة مشغّلك عند الانتهاء منه من خلال إضافة السطر التالي إلى الجزء السفلي من اختبار الملف quick_test.js:

driver.quit();

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

أفضل ممارسات في عملية الاختبار

يجب أن تتأكد من أن اختباراتك تطبّق ما يلي:

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

ثانيًا، تكتب اختبارات ذرية: يجب أن يختبر كل اختبار شيئًا واحدًا فقط، مما يسهل تعقّب ملف الاختبار الذي يختبر معيارًا معينًا، ويُعَدّ اختبار الملف google_test.js الذي ناقشناه سابقًا مثالًا جيدًا لأنه يختبر شيئًا واحدًا فقط، إذ يختبر ما إذا كان عنوان صفحة نتائج البحث مضبوطًا بصورة صحيحة، كما يمكننا إعطاء هذا الملف اسمًا أفضل حتى يسهل معرفة ما يفعله إذا أضفنا اختبارات جوجل أخرى مثل الاسم results_page_title_set_correctly.js.

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

كما يجب أن نذكر نتائج أو تقرير الاختبار، إذ أصدرنا تقريرًا بالنتائج في الأمثلة السابقة باستخدام تعليمات console.log()‎ البسيطة، ولكن يحدث كل ذلك في شيفرة جافاسكربت، لذا يمكنك استخدام أيّ نظام اختبار تريده لتشغيل الاختبار وإعداد التقارير سواءً كان Mocha أو Chai أو أيّ أداة أخرى.

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

ثانيًا، ثبّت أداة الاختبار Mocha عبر تشغيل الأمر التالي ضمن مجلد مشروعك:

npm install --save-dev mocha

يمكنك الآن تشغيل الاختبار وأيّ اختبارات أخرى تضعها ضمن مجلد test باستخدام الأمر التالي:

npx mocha --no-timeouts

يجب عليك تضمين الراية ‎--no-timeouts للتأكد من عدم فشل اختباراتك بسبب مهلة Mocha التي هي 3 ثوان.

إجراء الاختبارات عن بعد

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

LambdaTest

يُعَدّ إجراء اختبارات Selenium عن بُعد على نظام LambdaTest أمرًا بسيطًا، ويجب أن تتّبع الشيفرة البرمجية التي تحتاجها النمطَ الآتي.

إذًا لنكتب مثالًا يوضّح إجراء اختبارات Selenium عن بُعد على نظام LambdaTest:

أولًا، أنشئ ملفًا جديدًا بالاسم lambdatest-google_test.js ضمن مجلد المشروع.

ثانيًا، ضع فيه المحتويات التالية:

const webdriver = require('selenium-webdriver');
const By = webdriver.By;
const until = webdriver.until;

// username: يمكن العثور على اسم المستخدِم في لوحة تحكم الأتمتة
const USERNAME = '{username}';

// AccessKey: يمكن توليد مفتاح الوصول من لوحة تحكم الأتمتة أو قسم الملف الشخصي
const KEY = '{accessKey}';

// gridUrl: يمكن العثور عليه في لوحة تحكم الأتمتة
const GRID_HOST = 'hub.lambdatest.com/wd/hub';

function searchTextOnGoogle() {
// إعداد إمكانات الإدخال
    const capabilities = {
       platform: 'windows 10',
       browserName: 'chrome',
       version: '67.0',
       resolution: '1280x800',
       network: true,
       visual: true,
       console: true,
       video: true,
       name: 'Test 1', // اسم الاختبار
       build: 'NodeJS build' // اسم البناء
     };

// URL: https://{username}:{accessToken}@hub.lambdatest.com/wd/hub

const gridUrl = `https://${USERNAME}:${KEY}@${GRID_HOST}`;

// إعداد وبناء كائن مشغّل‫ selenium
 const driver = new webdriver.Builder()
    .usingServer(gridUrl)
    .withCapabilities(capabilities)
    .build();

// ‫انتقل إلى عنوان url، وابحث عن نص واحصل على عنوان الصفحة
driver.get('https://www.google.com/ncr').then(function() {
    driver.findElement(webdriver.By.name('q')).sendKeys('LambdaTest\n').then(function() {
         driver.getTitle().then((title) => {
               setTimeout(() => {
                 console.log(title);
                 driver.quit();
                 }, 5000);
            });
         });
      });
   }

searchTextOnGoogle();

ثالثًا، انتقل إلى لوحة تحكم أتمتة LambdaTest لجلب اسم مستخدِم LambdaTest ومفتاح الوصول من خلال النقر على رمز المفتاح في أعلى اليمين، حيث سترى اسم المستخدِم Username ومفاتيح الوصول Access Keys، واستبدل العناصر البديلة {username} و {accessKey} في شيفرتك باسم المستخدِم وقيم مفتاح الوصول الفعلية وتأكّد من الحفاظ عليها آمنةً.

رابعًا، شغّل الأمر التالي في طرفيتك لتنفيذ اختبارك:

node lambdatest_google_test

سيُرسَل الاختبار إلى LambdaTest وسيظهر خرج الاختبار على طرفية LambdaTest، فإذا أردتَ استخراج هذه النتائج لإصدار التقارير من منصة LambdaTest، فيمكنك ذلك باستخدام واجهة برمجة تطبيقات LambdaTest.

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

01_automation-logs-1.jpg

يمكنك استرداد سجلات الشبكة والأوامر والاستثناءات و Selenium لكل اختبار في عملية بناء اختبارك، وستجد تسجيل فيديو لتنفيذ سكربت Selenium.

ملاحظة: سيوفر زر "المساعدة HELP" الموجود في لوحة تحكم أتمتة LambdaTest كميةً وافرةً من المعلومات لمساعدتك في بدء تشغيل اختبار LambdaTest الآلي.

ملاحظة: إذا لم ترغب في كتابة كائنات الإمكانات لاختباراتك يدويًا، فيمكنك إنشاؤها باستخدام منشئ إمكانات Selenium.

ملء تفاصيل الاختبار على LambdaTest برمجيا

يسهّل تمييز حالة الاختبارات الآلية المتعددة على أنها نجحت أو فشلت الأمورَ كثيرًا عند تنفيذها.

أولًا، استخدِم الأمر التالي لتمييز الحالة على أنها ناجحة في LambdaTest:

driver.executeScript("lambda-status=passed");

ثانيًا، استخدِم الأمر التالي لتمييز الحالة على أنها فاشلة في LambdaTest:

driver.executeScript("lambda-status=failed");

BrowserStack

يُعَدّ إجراء اختبارات Selenium للتشغيل عن بُعد على BrowserStack أمرًا سهلًا، إذ يجب أن تتبع الشيفرة البرمجية التي تحتاجها النمطَ الآتي.

لنكتب إذًا مثالًا يوضّح إجراء اختبارات Selenium للتشغيل عن بُعد على BrowserStack:

أولًا، أنشئ ملفًا جديدًا بالاسم bstack_google_test.js ضمن مجلد المشروع.

ثانيًا، ضع فيه المحتويات التالية:

const webdriver = require('selenium-webdriver');
const By = webdriver.By;
const until = webdriver.until;

// إمكانات الإدخال
let capabilities = {
   'browserName' : 'Firefox',
   'browser_version' : '56.0 beta',
   'os' : 'OS X',
   'os_version' : 'Sierra',
   'resolution' : '1280x1024',
   'browserstack.user' : 'YOUR-USER-NAME',
   'browserstack.key' : 'YOUR-ACCESS-KEY',
   'browserstack.debug' : 'true',
   'build' : 'First build'
};

const driver = new webdriver.Builder()
  .usingServer('http://hub-cloud.browserstack.com/wd/hub')
  .withCapabilities(capabilities)
  .build();

driver.get('http://www.google.com');
driver.findElement(By.name('q')).sendKeys('webdriver');

driver.sleep(1000).then(() => {
  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
});

driver.findElement(By.name('btnK')).click();

driver.sleep(2000).then(() => {
  driver.getTitle().then((title) => {
    if(title === 'webdriver - Google Search') {
      console.log('Test passed');
    } else {
      console.log('Test failed');
    }
  });
});

driver.quit();

ثالثًا، انتقل إلى لوحة تحكم أتمتة BrowserStack للحصول اسم مستخدِم ومفتاح الوصول، واستبدل العناصر البديلة YOUR-USER-NAME و YOUR-ACCESS-KEY في شيفرتك باسم المستخدِم وقيم مفتاح الوصول الفعلية وتأكّد من الحفاظ عليها آمنة.

رابعًا، شغّل اختبارك باستخدام الأمر التالي:

node bstack_google_test

سيُرسَل الاختبار إلى BrowserStack وستُعاد نتيجة الاختبار إلى طرفيتك، ويدل ذلك على أهمية تضمين آلية لإعطاء تقارير بالنتائج.

أخيرًا، إذا عدت الآن إلى صفحة لوحة تحكم أتمتة BrowserStack، فسترى اختبارك موجودًا هناك:

02_bstack_automated_results.png

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

ملاحظة: يحتوي خيار قائمة الموارد Resources في لوحة تحكم أتمتة Browserstack على مجموعة كبيرة من المعلومات المفيدة حول استخدامه لإجراء الاختبارات الآلية.

ملاحظة: إذا لم ترغب في كتابة كائنات الإمكانات لاختباراتك يدويًا، فيمكنك إنشاؤها باستخدام منشئ إمكانات Selenium.

ملء تفاصيل اختبار BrowserStack برمجيا

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

لنعدّل bstack_google_test.js لإظهار كيفية عمل هذه الميزات:

يجب أولًا استيراد وحدة طلب Node لنتمكّن من استخدامها لإرسال الطلبات إلى واجهة REST API، لذا أضِف السطر التالي في بداية شيفرتك البرمجية:

const request = require("request");

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

'project' : 'Google test 2'

يجب بعد ذلك الوصول إلى المعرّف sessionId للجلسة الحالية لنعرف مكان إرسال الطلب، حيث يُضمَّن المعرّف في عنوان URL الخاص بالطلب كما سنرى لاحقًا. ضمّن الأسطر التالية بعد الكتلة التي تنشئ الكائن driver (أي let driver ...‎?

let sessionId;

driver.session_.then((sessionData) =>{
  sessionId = sessionData.id_;
});

أخيرًا، عدّل الكتلة driver.sleep(2000) ...‎ بالقرب من أسفل شيفرتك لإضافة استدعاءات واجهة REST API، ولا تنسى استبدال العناصر البديلة YOUR-USER-NAME و YOUR-ACCESS-KEY في شيفرتك البرمجية باسم المستخدِم وقيم مفتاح الوصول الفعلية:

driver.sleep(2000).then(() => {
  driver.getTitle().then((title) => {
    if(title === 'webdriver - Google Search') {
      console.log('Test passed');
      request({
         uri: `https://YOUR-USER-NAME:YOUR-ACCESS-KEY@www.browserstack.com/automate/sessions/${sessionId}.json`, 
         method:"PUT", 
         form:{"status":"passed","reason":"Google results showed correct title"}}
      );
    } else {
      console.log('Test failed');
      request({
         uri: `https://YOUR-USER-NAME:YOUR-ACCESS-KEY@www.browserstack.com/automate/sessions/${sessionId}.json`, 
         method:"PUT", 
         form:{"status":"failed","reason":"Google results showed wrong title"}}
      );
    }
  });
});

سنرسل استدعاء واجهة API إلى BrowserStack بعد اكتمال الاختبار لتحديثه بحالة النجاح أو الفشل وبسبب النتيجة.

إذا عُدتَ الآن إلى صفحة لوحة تحكم أتمتة BrowserStack، فيجب أن ترى جلسة اختبارك متاحةً كما كانت سابقًا ولكن مع البيانات المحدَّثة المرفقة بها:

03_bstack_custom_results.png

Sauce Labs

يُعَدّ إجراء اختبارات Selenium للتشغيل عن بُعد في Sauce Labs أمرًا بسيطًا، ويشبه إلى حد كبير اختبار BrowserStack مع بعض الاختلافات الصياغية، كما يجب أن تتّبع الشيفرة البرمجية التي تحتاجها النمط الآتي.

لنكتب إذًا مثالًا يوضّح إجراء اختبارات Selenium للتشغيل عن بُعد على Sauce Labs:

أولًا، أنشئ ملفًا جديدًا بالاسم sauce_google_test.js ضمن مجلد مشروعك.

ثانيًا، ضع فيه المحتويات التالية:

const webdriver = require('selenium-webdriver');
const By = webdriver.By;
const until = webdriver.until;
const username = "YOUR-USER-NAME";
const accessKey = "YOUR-ACCESS-KEY";

const driver = new webdriver.Builder()
    .withCapabilities({
      'browserName': 'chrome',
      'platform': 'Windows XP',
      'version': '43.0',
      'username': username,
      'accessKey': accessKey
    })
    .usingServer(`https://${username}:${accessKey}@ondemand.saucelabs.com:443/wd/hub`)
    .build();

driver.get('http://www.google.com');

driver.findElement(By.name('q')).sendKeys('webdriver');

driver.sleep(1000).then(() => {
  driver.findElement(By.name('q')).sendKeys(webdriver.Key.TAB);
});

driver.findElement(By.name('btnK')).click();

driver.sleep(2000).then(() => {
  driver.getTitle().then((title) => {
    if(title === 'webdriver - Google Search') {
      console.log('Test passed');
    } else {
      console.log('Test failed');
    }
  });
});

driver.quit();

ثالثًا، انتقل إلى إعدادات مستخدِم Sauce Labs للحصول اسم المستخدِم ومفتاح الوصول، واستبدل العناصر البديلة YOUR-USER-NAME و YOUR-ACCESS-KEY في شيفرتك باسم المستخدِم وقيم مفتاح الوصول الفعلية وتأكّد من الحفاظ عليها آمنة.

رابعًا، شغّل اختبارك باستخدام الأمر التالي:

node sauce_google_test

سيُرسَل الاختبار إلى Sauce Labs وستُعاد نتيجة الاختبار إلى طرفيتك، إذ يدل ذلك على أهمية تضمين آلية لإعطاء تقارير بالنتائج.

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

04_sauce_labs_automated_test.png

ملاحظة: تُعَدّ أداة إعداد منصة Sauce Labs أداةً مفيدةً لإنشاء كائنات الإمكانات لتقديمها إلى نسخ المشغّلات بناءً على المتصفح/نظام التشغيل الذي تريد الاختبار عليه.

ملء تفاصيل اختبار Sauce Labs برمجيا

يمكنك استخدام Sauce Labs API للتعليق على اختبارك بمزيد من التفاصيل مثل نجاح الاختبار واسم الاختبار وغير ذلك، إذ لا يعرف Sauce Labs هذه التفاصيل افتراضيًا.

يمكن تطبيق ذلك كما يلي:

أولًا، ثبّت المغلّف Node Sauce Labs باستخدام الأمر التالي (إذا لم تفعل ذلك مسبقًا في هذا المشروع):

npm install saucelabs --save-dev

ثانيًا، اطلب saucelabs في أعلى الملف sauce_google_test.js بعد التصريح عن المتغيرات:

const SauceLabs = require('saucelabs');

ثالثًا، أنشئ نسخةً جديدةً من SauceLabs من خلال إضافة ما يلي:

let saucelabs = new SauceLabs({
    username : "YOUR-USER-NAME",
    password : "YOUR-ACCESS-KEY"
});

لا تنسى استبدال العناصر البديلة YOUR-USER-NAME و YOUR-ACCESS-KEY في شيفرتك باسم المستخدِم وقيم مفتاح الوصول الفعلية، ولاحظ أنّ حزمة saucelabs npm تستخدِم كلمة المرور password وليس مفتاح الوصول accessKey، وبما أنك تستخدِم هاتين القيمتين، فيمكن أن ترغب في إنشاء متغيرين مساعدَين لتخزينهما فيهما.

رابعًا، أضِف الكتلة التالية بعد كتلة تعريف المتغير driver بعد سطر build()‎ مباشرةً، حيث تحصل هذه الكتلة على معرّف جلسة sessionID المشغّل الصحيح الذي نحتاجه لكتابة البيانات في الوظيفة، حيث يمكنك رؤية هذا المعرّف قيد التشغيل في كتلة الشيفرة البرمجية التالية:

driver.getSession().then((sessionid) => {
      driver.sessionID = sessionid.id_;
});

أخيرًا، استبدل الكتلة driver.sleep(2000) ...‎ الموجودة في أسفل الشيفرة البرمجية بما يلي:

driver.sleep(2000).then(() => {.then(function() {
  driver.getTitle().then((title) => {
    let testPassed = false;
    if(title === 'webdriver - Google Search') {
      console.log('Test passed');
      let testPassed = true;
    } else {
      console.log('Test failed');
    }

    saucelabs.updateJob(driver.sessionID, {
      name: 'Google search results page title test',
      passed: testPassed
    });
  });
});

ضبطنا هنا المتغير testPassed على القيمة true أو false اعتمادًا على نجاح الاختبار أو فشله، ثم استخدمنا التابع saucelabs.updateJob()‎ لتحديث التفاصيل.

إذا عُدتَ الآن إلى صفحة لوحة تحكم أتمتة Sauce Labs، فسترى أن وظيفتك الجديدة تحتوي الآن على البيانات المُحدَّثة المرفقة بها:

05_sauce_labs_updated_job_info.png

خادمك البعيد

إذا لم ترغب في استخدام خدمة مثل Sauce Labs أو BrowserStack، فيمكنك دائمًا إعداد خادمك للاختبار عن بُعد كما يلي:

أولًا، يتطلب خادم Selenium البعيد تشغيل شيفرة جافا، لذا يجب عليك تنزيل أحدث إصدار من JDK لمنصتك من صفحة تنزيلات Java SE، ثم ثبّته بعد تنزيله.

ثانيًا، نزّل خادم Selenium المستقل الأحدث الذي يعمل بوصفه وكيلًا proxy بين السكربت ومشغّلات المتصفح، ثم اختر أحدث رقم إصدار مستقر -أي ليس إصدارًا تجريبيًا beta- واختر من القائمة ملفًا يبدأ بعبارة "selenium-server-standalone"، ثم ضعه في مكان يمكنك الوصول إليه بسهولة بعد تنزيله مثل مجلدك الرئيسي، كما يجب إضافة الموقع إلى المتغير PATH إذا لم تفعل ذلك بعد.

ثالثًا، شغّل الخادم المستقل من خلال إدخال ما يلي في طرفية حاسوب خادمك:

java -jar selenium-server-standalone-3.0.0.jar

عدّل اسم الملف ‎.jar بحيث يتطابق تمامًا مع ملفك.

رابعًا، سيعمل الخادم على http://localhost:4444/wd/hub، لذا انتقل إلى هناك الآن لترى ما ستحصل عليه.

لدينا الآن الخادم قيد التشغيل، فلننشئ اختبارًا تجريبيًا يعمل على خادم Selenium البعيد:

  1. أنشئ نسخةً من الملف google_test.js بالاسم google_test_remote.js وضعه في مجلد مشروعك.
  2. عدّل كتلة الشيفرة البرمجية الثانية التي تبدأ بالسطر let driver = ...‎ كما يلي:
let driver = new webdriver.Builder()
    .forBrowser('firefox')
    .usingServer('http://localhost:4444/wd/hub')
    .build();
  1. شغّل اختبارك وسترى أنه يعمل بالشكل المتوقع، ولكنه سيعمل هذه المرة على الخادم المستقل:
node google_test_remote.js

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

دمج Selenium مع أدوات CI

يمكن دمج Selenium والأدوات المتعلقة به مثل LambdaTest و Sauce Labs مع أدوات التكامل المستمر Continuous Integration أو CI اختصارًا، إذ يُعَدّ ذلك مفيدًا لأنه يعني أنه يمكنك إجراء اختباراتك عبر أداة CI وإجراء تغييرات جديدة في مستودع شيفرتك البرمجية فقط إذا نجحت الاختبارات.

نقترح عليك البدء باستخدام أداة Travis CI التي تُعَدّ أسهل أداة CI للبدء بها ولديها تكامل جيد مع أدوات الويب مثل GitHub و Node.

ملاحظة: إذا أردتَ إجراء اختبار مستمر باستخدام اختبار آلي بدون شيفرة برمجية، فيمكنك استخدام أداة Endtest أو TestingBot.

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

ترجمة -وبتصرُّف- للمقال Setting up your own test automation environment.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...