понедельник, 17 ноября 2014 г.

Легкий способ начать автоматизировать. Правильно определяем локаторы

Этой статьей я начинаю цикл публикаций, посвященных основам автоматизации тестирования веб-приложений с использованием инструмента Selenium WebDriver. Для того, чтобы овладеть столь необходимым навыком, нам потребуется сделать всего лишь 3 шага. Итак, приступим.
Шаг 1. Правильно определяем локаторы

Для чего же нужны локаторы и почему нужно правильно их определять? C помощью локатора мы говорим WebDriver какой именно элемент на странице ему нужно найти и выполнить определенные действия.
Если, для написания автоматизированных тестов, используется Selenium, то локатор указывается в поле target, если selenium WebDriver, то локатор передается в метод findElement. (WebElement element = driver.findElement(By.name("q")).
Если мы плохо (некачественно) определим локатор, то есть большая вероятность того, что при выполнении теста WebDriver не найдет нужный элемент и весь тест тут же завершиться ошибкой.
Теперь определимся с инструментарием. Для определения локаторов я буду использовать дополнения firebug и firepath для браузера Firefox, которые можно загрузить из меню Дополнения браузера.  Firepath является дополнением Firebird и, помимо показа тэгов и атрибутов элементов, позволяет писать и проверять css и xpath выражения.
Для отображения атрибутов элемента веб-страницы, нужно активировать Firebug и кликнуть по элементу.
Каждый элемент на веб-странице представлен html-тэгом и набором атрибутов. Для определения локатора мы можем использовать все атрибуты элемента. Selenium использует следующие типы локаторов:
  • Id
  • name
  • link
  • css
  • xpath
Разберем каждый из них по порядку:

ID

Определение локатора по идентификатору элемента (атрибут id) – является самым простым. Находим элемент на странице, кликаем по нему и в firebug смотрим его id. Например, на приведенном ниже на рисунке примере, id элемента будет равен «gs_htif0».

Главным минусом определения локатора по идентификатору является то, что очень часто элементы имеют динамичные id, которые изменяются при каждой новой загрузке страницы, вследствие чего ваши автотесты будут непригодны для использования.

Name 

Определение локатора по атрибуту name элемента очень часто используется при работе уникальными полями для ввода, такими как поля для ввода логина и пароля. Принцип определения такой же, как и у id. Кликаем по элементу и среди набора атрибутов ищем атрибут name и его значение.
Часто бывает, что элементов с одинаковым атрибутом name на странице несколько. В таком случае, использовать локатор с типом name нельзя, так как он не позволит уникальным образом идентифицировать элемент.

Link или же LinkText.

Определение локатора по тексту ссылки, как следует из названия, необходимо использовать для ссылок. Локатором в этом случает будет являться текст ссылки.
В примере на рисунке локатор определим, как link = ”вспомнить пароль”.

Три вышеперечисленных типа локаторов относятся к простым. Что же делать, если при помощи этих типов нельзя уникально идентифицировать элемент на странице (id динамичный, а атрибут name одинаков для нескольких элементов)? Тут нам на помощь приходят следующие 2 типа локаторов, так называемая «высшая лига», css и xpath. При помощи этих типов, мы сможем идентифицировать элементы при помощи всех его атрибутов или же при помощи расположения элемента на странице относительно других элементов.

CSS

Сначала рассмотрим те CSS выражения, которые буду выполнять поиск элемента на странице по связке html тэг-атрибут. К элементу на странице мы можем обратиться по его идентификатору (id). Синтаксис будет следующий:
#id. Так, выражение #auth-haunter, найдет элемент(ы), у которых атрибут id=auth-haunter.

Можно найти элемент по наименованию класса:
.class – выражение .checkbox__control найдет все элементы, у которых атрибут class=checkbox__control
Можно обратиться к элементу напрямую, для этого достаточно просто указать html тэг элемента. Так, тэг button найдет все элементы button на странице.
При составлении СSS выражений, мы можем комбинировать тэги и атрибуты. Так, выражение input#auth-haunter найдет нам элемент input у которого id= auth-haunter, а выражение input.checkbox__control, найдет нам элемент input, у которого атрибут class = checkbox__control. Как видно из рисунка ниже, это будет один и тот же элемент :)
Для того, чтобы найти элемент по любому другому атрибуту, используется следующая форма записи:
element[attribute] – так, выражение button[type] найдет на странице все элементы button, у которых есть атрибут type
При помощи CSS мы может строить выражения, которые будут находить элемент на странице при помощи его тэга, атрибута и значения атрибута.
element[attribute =”value”] – строгое совпадение по значению. Так, выражение input[title=”Search”] найдет нам элемент input, у которого значение атрибута title = Search
element[attribute^=”value”] – значение атрибута начинается со строки value
element[attribute$=”value”] – значение атрибута заканчивается строкой value
element[attribute*=”value”] – значение атрибута содержит строку value
Например, button[value$="Web"] найдет элемент button, у которого атрибут value заканчивается словом Web
Иногда необходимо найти элемент по его расположению относительно другого элемента (вторая ссылка в списке, третья запись в таблице). Нужно понимать, что структура элементов на странице представляет из себя дерево, где элементы находятся в отношении родитель – потомок.
Рассмотрим, как  нам строить css выражения в таких случаях.
element1 element2 – ищет среди всех потомков element1 нужный element2. Например, div input найдет все элементы input, которые являются потомками элемента div
element1 > element2 – найдет нужный element2, который является непосредственным потомком element1. Так из примера выше, элементы input являются потомками div, но непосредственными потомками они являются дял элемента form. Поэтому для их поиска можно написать следующее выражение: form>input
element1 + element2 – ищет нужный element2, который располагается сразу за element1.
В нашем примере, input располагается сразу за элементом i. Найдем элемент input выражением: i+input
element:nth-of-type(n) – ищет элемент, который расположен n-ым по счету. Так, для того, чтобы найти второй input из нашего примера, можно написать следующее выражение: form>input:nth-of-type(2) (Среди прямых потомков элемента form найти элемент input, который будет располагаться 2-м по счету).
Итак, мы рассмотрели основные принципы построения css выражений. Комбинируя их, мы можем уникально идентифицировать практически любой элемент на странице.

Xpath

Xpath выражения осуществляют поиск по xml разметке веб-страницы. Любое xpath выражение начинается со знака «/», который обозначает корень дерева элементов на странице.
Рассмотрим синтаксис основных xpath выражений:
* - любые элементы
// - поиск по всем потомкам, так выражение //div произведет поиск по всем элементам, начиная от корня и найдет все элементы div
Xpath, как и css, позволяет искать элементы по связке тэг-атрибут. Для обращения к атрибуту используется символ «@». Синтаксис в этом случае будет следующий: //element[@attribute=”value”]. Например, выражение //input[@title="Search"] говорит, что нужно искать среди всех элементов, начиная с корня, все элементы Input, у которых атрибут title = Search
Если элемент содержит какой-либо текст, мы может обратиться к нему используя функцию text()=”value” (//element[text()=”value”]).
//em[text()="Mail"] – найдет на странице элемент em с текстом Mail.
Если на странице идет несколько одинаковых элементов подряд, то при поиске можно указать позицию элемента функцией position()=value, или же [value]. Выражения //div/input[position()=3]) или //div/input[3] найдут элемент input, который является потомком элемента div и является 3-им по счету.
Xpath также поддерживает логические выражения «И» и «ИЛИ».
Для «ИЛИ» синтаксис следующий: //element[@attribute=”value” or @attribute=”value”]. Например //input[@type="text" or @name="cop"] найдет среди всех элементов страницы элементы input, у которых атрибут type=text или атрибут name=cop.
Для «И» выражение будет выглядеть следующим образом: //element[@attribute=”value” and @attribute=”value”]. //input[position()=2 and @value="Go"] – среди всех элементом страницы найдет элемент input, который располагается вторым и у которого атрибут value = Go.
Мы рассмотрели наиболее часто употребляемые способы написания локаторов при помощи xpath. Есть еще одно правило, которое касается как xpath, так и css выражений – нужно избегать использования промежуточных локаторов (длинных выражений), так как такие локаторы очень чувствительны к изменениям. Т.е. чем меньше элементов мы задействуем в определении локатора, тем он будет надежней. Например, локатор //*[@id='default-p_30345827-bd']/div/div/ol/li[1]/a лучше преобразовать к виду //*[@id='default-p_30345827-bd']//li[1]/a, убрав промежуточную часть (/div/div/ol/). Как видим из примера, и в том, и в другом случае будет найдет один и тот же элемент.

И напоследок еще один совет: Всегда старайтесь при определении локатора следовать принципу от простого к сложному. Пытайтесь определять локаторы при помощи простых типов (id, name, link) и используйте сложные (css, xpath) только в случае необходимости.
На этом с локаторами все, следующий раз мы научимся писать и запускать автоматизированные тесты при помощи Selenuim Web-Driver.

2 комментария:

  1. Для «ИЛИ» синтаксис следующий: //element[@attribute=”value” or @attribute=”value”]. Например //input[@type="text" or name="cop"] - а почему в примере перед атрибутом "name" нету символа "@"?

    ОтветитьУдалить
    Ответы
    1. Описка вышла, спасибо, исправил в тексте. Конечно же, символ @ нужен.

      Удалить