Что пишут в блогах

Подписаться

Что пишут в блогах (EN)

Разделы портала

Онлайн-тренинги

.
Локаторы веб-элементов в тест-автоматизации
12.08.2019 00:00

Автор: Энди Найт (Andy Knight)
Оригинал статьи
Перевод: Ольга Алифанова

Если вы занимаетесь тест-автоматизацией через веб-интерфейс (например, при помощи Selenium WebDriver), то, возможно, тратите много рабочего времени на поиск элементов на странице – к примеру, кнопок, полей ввода и блоков. Поиск нужных элементов может быть сложным делом, особенно в тех случаях, когда у них нет уникальных идентификаторов или имен классов. Это руководство поможет вам профессионально находить любые веб-элементы.

Что такое веб-элементы?

Веб-элемент – это индивидуальная сущность, генерирующаяся на веб-странице. Элементы – это все то, что пользователь видит (а иногда и не видит) на странице – заголовки, кнопки "ОК", поля ввода, текстовые блоки… Элементы в HTML определяются через имя тэга, атрибуты и содержание. У них также могут быть дочерние элементы – например, таблицы. CSS может применяться к элементам и менять их цвета, размеры и расположение. Языки программирования обычно получают доступ к веб-элементам как к нодам в объектной модели документа (DOM).

Что такое локаторы веб-элементов?

Веб-элементы и локаторы – это разные вещи. Локатор веб-элемента – это объект, который находит и возвращает веб-элементы на странице по заданному запросу. Короче говоря, локаторы находят элементы.

Зачем нужны локаторы? Как пользователи, мы взаимодействуем с веб-страницами визуально. Мы смотрим, скроллим, кликаем и печатаем посредством браузера. Тест-автоматизация, однако, взаимодействует со страницами программно: ей нужен закодированный способ поиска и манипулирования теми же самыми элементами. Традиционная автоматизация не будет "смотреть" на страницу, как человек – вместо этого она будет искать через DOM.

(Более современные технологии автоматизации позволяют визуальное тестирование – об этом будет сказано чуть позже).

Selenium WebDriver разделяет вопросы поиска элементов и взаимодействия с ними. Вызовы WebDriver для этих двух целей часто идут подряд.

1
2
3
4
5
6
7
// Пример для WebDriver: ввод поискового запроса на www.google.com
// Этот код написан на C#, но вызовы аналогичны в любых других языках
 
// Вначале идет поиск элемента
IWebElement searchField = driver.FindElement(By.Name("q"));
 
// А затем взаимодействие с ним
searchField.SendKeys("panda");

WebDriver предоставляет следующие типы запросов для локаторов через "By":

provides the following locator query types using “By”:

Какой из них лучше? Обсудим далее.

Локаторы могут возвращать несколько элементов, или вообще их не вернуть! Вот пример:

1
2
3
4
5
// Получение результатов поиска Google
// Использование "FindElements" вернет список всех найденных элементов по порядку
// Использование "FindElement" вернет первый найденный элемент (или выдаст исключение, если элементы не найдены)
IList<IWebElement> results = driver.FindElements(By.CssSelector("div.r"));
results.Count.Should().BeGreaterThan(0);

Большие тест-фреймворки часто используют шаблоны дизайна для структурирования локаторов и взаимодействий. Модель Page Object организует локаторы и методы действий в классы – по странице или по компоненту. Однако я крайне рекомендую шаблон Screenplay, а не Page Object, потому что части Screenplay лучше подаются повторному использованию и масштабированию. Вне зависимости от модели локаторы необходимы.

Как найти элементы?

Элементы могут с трудом поддаваться поиску, когда вы пишете локаторы для тест-автоматизации. Для упрощения работы я использую инструменты разработчика Chrome вместе с моей IDE. Почему Chrome?

Чтобы исследовать любую страницу в Chrome, просто кликните правой кнопкой на любом месте страницы:


Вуаля! Инструменты разработчика откроются. Для поиска веб-элементов мы воспользуемся вкладкой Elements.


В Chrome легко выделить элемент визуально. Выберите инструмент "Select" в верхнем левом углу панели инструментов разработчика (она выглядит как квадрат с курсором). Иконка должна поменять цвет на синий.


Затем переместите курсор к нужному элементу на странице. Вы увидите, как каждый элемент подсвечивается, когда вы наводите на него мышь. Соответствующий исходный HTML-код на вкладке Elements также будет подсвечен. Чудненько! Кликните на нужном элементе, чтобы подсветка сохранилась после смещения курсора.


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

Как писать хорошие локаторы?

Поиск элемента – это полдела. Создание уникального запроса для локатора – вот вторая половина. Если локатор чересчур широк, он будет возвращать ложноположительные значения. При слишком узком подходе он начнет ломаться при любом изменении DOM, и его будет сложно читать другим людям. Лучший подход здесь такой – пишите наиболее простой запрос, который уникально идентифицирует целевой элемент или элементы.

Мой список предпочтения типов запросов в порядке убывания:

  1. ID (если уникален)
  2. Имя (если уникально)
  3. Имя класса
  4. CSS-селектор
  5. XPath без текста или индексирования
  6. Текст ссылки/частичный текст ссылки.
  7. XPath с текстом и/или индексированием.

Уникальные ID, имена и имена классов крайне упрощают создание локаторов: запросы будут краткими и не требуют дополнительных якорей. Всегда ратуйте, чтобы ваши разработчики использовали уникальные идентификаторы (например, имена классов) для всех элементов. Однако у многих элементов таких идентификаторов нет, и локаторам приходится полагаться на более сложные CSS-селекторы и (содрогнувшись) XPath. Если это случилось с вами, вот мои рекомендации:

  • Используйте родительские элементы как якоря, если у них есть уникальный идентификатор:
    • Пример CSS-селектора: “#some-list > li”
    • XPath-пример: “//ul[@id=’some-list’]/li”
  • Избегайте XPath с текстом/индексированием при любой возможности.
    • Плохой пример: “//div[3]//span[text()=’hello’]”
    • Это наиболее хрупкие тесты.
  • Используйте функцию "contains", проверяя классы в XPath.
    • Пример: “//div[contains(@class, ‘some-class’)]”
    • У элементов зачастую больше одного класса.
    • “contains” проверит подстроку вместо полной строки класса.
    • Но будьте осторожны, потому что под выдачу попадут также “some-class2”!

Всегда тестируйте локаторы, в них часто встречаются ошибки синтаксиса и ложноположительные значения. Chrome DevTools упрощает их тестирование – нажмите Ctrl+F на вкладке элементов и вставьте запрос локатора в поле поиска. DevTools подсветит все соответствующие элементы по порядку. Шик-блеск-красота!


Если я не могу разобраться, почему локатор в тесте не срабатывает, я делаю следующее:

  1. Запускаю тест без дебага со своей IDE.
  2. Устанавливаю на локаторе брейкпойнт.
  3. Жду, пока тест остановится.
  4. Захожу в DevTools в активном окне Chrome.
  5. Проверяю DOM и тестирую локатор на живой странице.

Что делать, если тесты нестабильны?

Тестирование через Web UI часто критикуют за нестабильность, потому что тесты часто падают из-за непредвиденных причин. Однако большая часть ненадежности, с которой сталкиваются тестировщики Web UI (и, зачастую, пользователи Selenium WebDriver как такового) связана с тем, что все Web-взаимодействия изначально создают гоночные условия. Автоматизация и браузер работают независимо друг от друга, и взаимодействие должно синхронизироваться с состоянием страницы. В противном случае WebDriver будет выдавать исключения из-за таймаутов, устаревших и не найденных элементов. В ряде случаев эти проблемы возникают не каждый раз, поэтому их тяжело отследить и исправить.

Лучший способ избежать гоночных условий таков – всегда ожидайте существования элемента, прежде чем взаимодействовать с ним. Это кажется элементарным, но про это легко забыть. Пакеты Selenium WebDriver всегда предлагают какую-то разновидность объекта WebDriverWait, заставляющего драйвер ожидать истинности определенного условия перед дальнейшими действиями. Простейший способ проверить, существует ли элемент – это проверить список элементов, возвращаемый вызовом FindElements (для списка элементов) и убедиться, что он непустой. Добавление дополнительного вызова для каждого взаимодействия может показаться затратным, однако дизайн-шаблоны хорошо спроектированных фреймворков (например, Screenplay) могут автоматически осуществлять подобные проверки.

Еще одна хорошая практика – всегда получать "свежие" элементы. Иногда автоматизация вначале получит ряд элементов, а затем через второй запрос получит следующую часть. Или же, в случае с Page Object Factory (никогда ей не пользуйтесь – если в трех словах, она отвратительна), элементы получаются один раз при конструировании Page Object, а затем на них ссылаются. Вне зависимости от способа – чем дольше существует объект на веб-странице, тем более он подвержен тому, чтобы устареть и вызвать исключения. Я видел элементы, необъяснимо устаревающие, даже если они еще присутствовали на странице. Всегда запрашивайте элемент тогда, когда он нужен – в этом случае он не успеет устареть!

Как искусственный интеллект может помочь в тестировании Web UI?

Ряд новых основанных на ИИ проектов и продуктов направлен на улучшение автоматизированного тестирования Web UI по сравнению с традиционными методами:

  • Applitools расширяет автоматизацию Selenium WebDriver, добавляя проверки на необычные визуальные различия.
  • Testim может автоматически исправлять сломанные локаторы, что позволяет избежать нестабильности тестов, связанной с изменениями фронтэнда.
  • Mabl – это помощник, который выучит и запустит тесты, которому его научили разработчики, без создания какого-либо кода.
  • Test.ai прогоняет распространенные пользовательские тесты вроде авторизации, поиска и покупок в мобильных приложениях, основываясь на знаниях ИИ о ряде других приложений.
  • Rainforest QA использует краудсорсинг и ИИ для прогона ручных тестов, конкретизированных командой, так, что они получаются почти как автоматизированные.

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

Обсудить в форуме