Рубрики
Без рубрики

Как писать надежные тесты браузера с использованием Selenium и Node.js

Chaffee ToDD Как написать надежные тесты браузера с помощью Selenium и Node.jsthere – это много хороших статей о том, как начать работу с автоматическим тестированием браузера с использованием версии селена Nodejs. Некоторые обертывают тесты в мокко или жасмин, а некоторые автоматикируют все с NPM или Grunt или

Автор оригинала: FreeCodeCamp Community Member.

Todd Chaffee

Есть много хороших статей о том, как начать работу с автоматизированным тестированием браузера с помощью версии Nodejs Selenium.

Некоторые обертывают тесты в Моча или Жасмин, а некоторые автоматикируют все с NPM или Grunt или Glp. Все они описывают, как установить то, что вам нужно, наряду с приведенным основым примером рабочего кода. Это очень полезно, потому что все разные части работают впервые, может быть проблемой.

Но они не хватают копания в деталях многих Gotchas и наилучшей практики автоматизации тестирования вашего браузера при использовании Selenium.

Эта статья продолжается, где эти другие статьи уходят, и поможет вам написать автоматические тесты браузера, которые намного более надежны и поддерживаются с помощью Nodejs Selenium API.

Избегать сна

Селен водитель Метод - твой худший враг. И все используют это. Это может быть потому, что документация для Node.js версия Селен обработан и только охватывает синтаксис API. Не хватает реальных образцов жизни.

Или это может быть потому, что множество примеров кода в блоге статей и на Q & A, такие как Stackoverflow, используют его.

Допустим, панель анимает от размера нуля, до полного размера. Давайте смотреть.

Это происходит так быстро, вы не можете заметить, что кнопки и элементы управления внутри панели постоянно меняются размер и положение.

Вот замедленная версия. Обратите внимание на зеленую кнопку закрытия, и вы можете увидеть изменяющийся размер и положение панели.

Это вряд ли проблема для реальных пользователей, потому что анимация происходит так быстро. Если бы это было достаточно медленно, вроде во втором видео, и вы пытались вручную нажать на кнопку «Закрыть», когда это происходит, вы можете нажать на неверную кнопку или совсем пропустить кнопку.

Но эти анимации обычно бывают так быстро, у вас никогда не будет шансов сделать это. Люди просто ждут анимации для завершения. Не правда с селен. Это так быстро, что он может попытаться нажать на элементы, которые все еще анимируются, и вы можете получить сообщение об ошибке, как:

System.InvalidOperationException : Element is not clickable at point (326, 792.5)

Это когда многие программисты скажут «ага! Я должен ждать анимации, чтобы закончить Так что я просто буду использовать драйвер. (1000) ждать, пока панель будет использоваться. “

Так в чем проблема?

Driver.sleep (1000) Заявление делает то, что похоже. Он прекращает выполнение вашей программы на 1000 миллисекунд и позволяет браузеру продолжить работу. Делая макет, выцветание или анимационные элементы, загрузка страницы или что-то еще.

Используя пример сверху, если панель исчезла в течение 800 миллисекунд драйвер. (1000) будет Обычно выполнить то, что вы хотите. Так почему бы не использовать это?

Самая важная причина в том, что это не детерминированные Отказ Это означает, что он будет работать только некоторое время. Так как он работает только некоторое время, мы в конечном итоге с хрупкими испытаниями, которые нарушаются в определенных условиях. Это дает автоматическое тестирование браузера плохое имя.

Почему это работает только некоторое время? Другими словами, почему это не детерминировано?

Что вы замечаете с вашими глазами, не часто единственное, что происходит на сайте. Элемент Fade-In или Animation является идеальным примером. Мы не должны заметить эти вещи, если они все хорошо.

Если вы скажете Selenium, чтобы сначала найдите элемент, а затем нажмите на него, могут быть только несколько миллисекундов между этими двумя операциями. Селен может быть гораздо быстрее человеческого.

Когда человек использует сайт, мы ждем, пока элемент выцветает, прежде чем нажать на него. И когда этот исчезновение занимает меньше секунды, мы, вероятно, даже не замечаем, что делаем это «ожидание». Selenium не только быстрее и меньше прощения, ваши автоматизированные тесты должны иметь дело со всеми видами других непредсказуемых факторов:

  1. Дизайнер вашей веб-страницы может изменить время анимации от 800 миллисекунд до 1200 миллисекунд. Ваш тест просто сломался.
  2. Браузеры не всегда делают именно то, что вы просите. Из-за нагрузки на систему анимация может фактически пробиваться и заниматься более 800 миллисекундров, может быть, даже дольше, чем ваш сон в размере 1000 миллисекунд. Ваш тест просто сломал Отказ
  3. Различные браузеры имеют разные двигатели макета и определяют приоритеты к операциям макета по-разному. Добавьте новый браузер в свой тестовый люкс и Ваши тесты просто сломались Отказ
  4. Браузеры и JavaScript, управляющие страницей асинхронной природой. Если анимация в нашем примере меняется функциональность, которая нуждается в информации с заднего конца, программист может добавить вызов AJAX и дождаться результата, прежде чем стрелять в анимацию. Сейчас мы имеем дело с сетевой задержкой и нулевой гарантией того, сколько времени зайдет для отображения панели. Ваш тест просто сломал Отказ
  5. Есть, безусловно, другие причины, о которых я не знаю. Даже один Браузер самостоятельно – сложный зверь, и все они имеют ошибки. Итак, мы говорим о попытке сделать то же самое на работу над несколькими Различные браузеры, несколько разных версий браузера, несколько разных операционных систем и несколько разных версий операционной системы. В какой-то момент Ваши тесты просто ломаются Если они не детерминированы. Никаких программистов не отказывается от автоматического тестирования браузера и жалуются на то, насколько хрупкие тесты.

Что обычно делают программисты, чтобы исправить вещи, когда происходит любой из вышеперечисленных? Они отслеживают вещи к проблемам с синхронизацией, поэтому очевидный ответ – это увеличить время в заявлении Driver.sleep. Затем пересекайте пальцы, что оно охватывает все возможные будущие сценарии нагрузки на систему, различия в движении макета и так далее. Это не детерминирован и Это разрывается Так что не делай этого!

Если вы еще не убеждены, вот еще одна причина: ваши тесты будут работать намного быстрее. Анимация из нашего примера занимает всего 800 миллисекунд, надеюсь. Чтобы справиться с «Мы надеемся» и сделайте тесты работы по всем условиям, которые вы, вероятно, увидите что-то вроде Driver.sleep (2000) в реальном мире.

Это более одного полного второго потерянного Всего за один шаг ваших автоматизированных тестов. На много шагов он быстро добавляет. Недавно рефакторированный тест на одну из наших веб-страниц, которые заняли несколько минут из-за чрезмерного использования водителя. Сейчас сейчас занимает менее пятнадцать секунд.

Большая часть остальной части этой статьи придает конкретные примеры о том, как вы можете сделать ваши тесты полностью детерминированными, и избежать использования водитель.

Примечание о обещаниях

API JavaScript для Selenium обеспечивает тяжелое использование обещаний, и он также делает хорошую работу, чтобы скрыть, что, используя встроенный менеджер обещаний. Это меняется и будет устареть .

В будущем вам потребуется научиться пользоваться цепочкой обещания себя или использовать новые функции Async JavaScript, такие как ждать Отказ

В этой статье примеры по-прежнему используют традиционный встроенный менеджер по обещанию Selenium и воспользоваться цепочкой обещания. Примеры кода здесь будут иметь больше смысла, если вы понимаете, насколько обещает работу. Но вы все еще можете получить много из этой статьи, если вы хотите пропустить обучение обещаниям на данный момент.

Давай начал

Продолжая на нашем примере кнопки, которую мы хотим нажать на панель, которая анимает, давайте посмотрим на несколько конкретных Gotchas, которые могут сломать наши тесты.

Как насчет элемента, который динамически добавляется на страницу и даже даже не существует после завершения страницы?

В ожидании присутствующего элемента в доме

Следующий код не будет работать, если элемент с идентификатором CSS «My-Button» был добавлен в DOM после нагрузки страницы:

// Selenium initialization code left out for clarity
// Load the page.driver.get('https:/foobar.baz');
// Find the element.const button = driver.findElement(By.id('my-button'));
button.click();

водитель. Финдометр Метод ожидает, что элемент уже присутствует в доме. Это будет ошибка, если элемент не может быть найден немедленно. В этом случае немедленно означает «после загрузки страницы завершена» из-за предыдущего Заявление Driver.get Отказ

Помните, что текущая версия javaScript Selenium управляет обещанием для вас. Таким образом, каждое утверждение будет полностью завершено, прежде чем перейти к следующему утверждению.

Примечание: Вышеуказанное поведение не всегда нежелательно. водитель. Финдометр На самом деле может быть действительно удобным, если вы уверены, что элемент уже должен быть там.

Сначала давайте посмотрим на неправильный способ исправления этого. Сказавшим, что это может потребоваться несколько секунд для элемента в DOM:

driver.get('https:/foobar.baz');
// Page has been loaded, now go to sleep for a few seconds.driver.sleep(3000);
// Pray that three seconds is enough and find the element.const button = driver.findElement(By.id('my-button'));
button.click();

По всем причинам, упомянутым ранее, это может сломаться, и, вероятно, будет. Нам нужно узнать, как ждать, пока будет расположен элемент. Это довольно легко, и вы увидите это часто в примерах со всей сети. В приведенном ниже примере мы используем Хорошо документировано Водитель. Работает Метод ждать до двадцати секунды для элемента, который можно найти в DOM:

const button = driver.wait(  until.elementLocated(By.id('my-button')),   20000);
button.click();

Для этого есть немедленные преимущества. Например, если элемент добавляется к DOM за одну секунду, метод Driver.Wait завершится через одну секунду. Это не будет ждать полных двадцать секунд.

Из-за такого поведения мы можем поставить нагрузку на прокладку в наше время ожидания, не беспокоясь о тайм-ауте, замедляя наши тесты. В отличие от водитель который всегда будет ждать все указанное время.

Это работает во многих случаях. Но один случай, если он не работает, пытается щелкнуть элемент, который присутствует в DOM, но еще не виден.

Селен достаточно умный, чтобы не щелкнуть элемент, который не виден. Это хорошо, потому что пользователи не могут щелкнуть невидимыми элементами, но это заставляет нас работать усерднее при создании надежных автоматизированных тестов.

Ожидание, пока элемент не будет видимым

Мы будем строить на приведенном выше примере, потому что имеет смысл ждать, пока элемент будет расположен до того, как он становится видимым.

Вы также найдете наше первое использование цепочки обещаний ниже:

const button = driver.wait(  until.elementLocated(By.id('my-button')),   20000).then(element => {   return driver.wait(     until.elementIsVisible(element),     20000   );});
button.click();

Мы могли бы почти остановиться здесь, и вы уже были бы намного лучше. С вышеупомянутым, вы устраните нагрузки тестовых случаев, которые в противном случае разбили бы, потому что элемент не сразу присутствует в доме. Или потому что он не сразу виден из-за таких вещей, как анимация. Или даже по обеим причинам.

Теперь, когда вы понимаете техника, никогда не должно быть причина для записи кода Selenium, который не является детерминированным. Это не сказать, что это всегда легко.

Когда все становится сложнее, разработчики часто снова сдаются и прибегают к водитель Отказ Надеюсь, давая еще больше примеров, я могу побудить вас сделать ваши тесты детерминированными.

Написание собственных условий

Благодаря до Метод, javaScript Selenium API уже имеет Горсть удобных методов Вы можете использовать с водитель . Вы также можете дождаться, пока элемент больше не существует, для элемента, содержащего конкретный текст, для присутствия присутствия оповещения или многие другие условия.

Если вы не можете найти то, что вам нужно в прилагаемом удобстве, вам нужно будет написать свои собственные условия. Это на самом деле довольно легко, но сложно найти примеры. И есть одна чтание – что мы доберемся.

Согласно документации , вы можете предоставить Водитель. Работает с функцией, которая возвращает правда или ложный .

Допустим, мы хотели дождаться элемента, чтобы быть полной непрозрачностью:

// Get the element.const element = driver.wait(  until.elementLocated(By.id('some-id')),  20000);
// driver.wait just needs a function that returns true of false.driver.wait(() => {   return element.getCssValue('opacity')          .then(opacity => opacity === '1');});

Это кажется полезным и многоразовым, поэтому давайте поставим его в функцию:

const waitForOpacity = function(element) {  return driver.wait(element => element.getCssValue('opacity')          .then(opacity => opacity === '1');  );};

И тогда мы можем использовать нашу функцию:

driver.wait(  until.elementLocated(By.id('some-id')),  20000).then(waitForOpacity);

Вот идут Готча. Что если мы хотим нажать на элемент после того, как он достигнет полной непрозрачности? Если мы попытаем назначить значение, возвращенное выше, мы не получим то, что мы хотим:

const element = driver.wait(  until.elementLocated(By.id('some-id')),  20000).then(waitForOpacity);
// Oops, element is true or false, not an element.element.click();

Мы не можем использовать цепочки обещания либо по той же причине.

const element = driver.wait(  until.elementLocated(By.id('some-id')),  20000).then(waitForOpacity).then(element => {  // Nope, element is a boolean here too.  element.click();}); 

Это легко исправить. Вот наш улучшенный метод:

const waitForOpacity = function(element) {  return driver.wait(element => element.getCssValue('opacity')          .then(opacity => {      if (opacity === '1') {        return element;      } else {        return false;    });  );};

Вышеуказанный шаблон, который Возвращает элемент, когда условие является правдой , и возвращает false в противном случае, это многоразовый шаблон, который вы можете использовать при написании собственных условий.

Вот как мы можем использовать его с цепочкой обещания:

driver.wait(  until.elementLocated(By.id('some-id')),  20000).then(waitForOpacity).then(element => element.click());

Или даже:

const element = driver.wait(  until.elementLocated(By.id('some-id')),  20000).then(waitForOpacity);
element.click();

Написав свои собственные простые условия, вы можете расширить ваши варианты для того, чтобы сделать ваши тесты детерминированными. Но это не всегда достаточно.

Идти отрицательно

Это верно, иногда вам нужно быть отрицательным, а не позитивным. То, что я имею в виду под этим, – это тестировать на что-то больше не существовать или для чего-то не быть видимым.

Допустим, элемент существует уже в доме, но вы не должны взаимодействовать с ним, пока некоторые данные не будут загружены через AJAX. Элемент может быть покрыт панелью «Loading …».

Если вы уделите пристальное внимание условиям, предлагаемым до Метод, вы могли бы заметить методы, такие как ElementiSnotvisile. или elementisdisabled. Или не так очевидно Стабильность элемента .

Вы можете проверить панель «Загрузка …» больше не быть видимой:

// Already added to the DOM, so this will return immediately.const desiredElement = driver.wait(  until.elementLocated(By.id('some-id')),  20000);
// But the element isn't really ready until the loading panel// is gone.driver.wait(  until.elementIsNotVisible(By.id('loading-panel')),  20000);
// Loading panel is no longer visible, safe to interact now.desiredElement.click();

Я нахожу Станзестиосплата быть особенно полезным. Он ждет, пока элемент не будет удален с DOM, который также может произойти из обновления страниц.

Вот пример ожидания содержания Iframe освежить перед продолжением:

let iframeElem = driver.wait(  until.elementLocated(By.className('result-iframe')),  20000  );
// Now we do something that causes the iframe to refresh.someElement.click();
// Wait for the previous iframe to no longer exist:driver.wait(  until.stalenessOf(iframeElem),  20000);
// Switch to the new iframe. driver.wait(  until.ableToSwitchToFrame(By.className('result-iframe')),  20000);
// Any following code will be relative to the new iframe.

Всегда быть детерминированным, и не спать

Я надеюсь, что эти примеры помог вам лучше понять, как сделать ваши тесты Selenium Detrinistic. Не полагайтесь на водитель с произвольным предположением.

Если у вас есть вопросы или ваши собственные методы для создания детерминированных испытаний Selenium, пожалуйста, оставьте комментарий.

Оригинал: “https://www.freecodecamp.org/news/how-to-write-reliable-browser-tests-using-selenium-and-node-js-c3fdafdca2a9/”