Поиск элементов в Appium

С использованием стабильных и точных методов идентификации элементов в Appium, вы снизите вероятность нестабильности тестов и повысите надежность мобильных приложений.

локаторы и селекторы в appium

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

Содержание:

Подпишитесь на наш ТЕЛЕГРАМ КАНАЛ ПО АВТОМАТИЗАЦИИ ТЕСТИРОВАНИЯ

Поиск элементов

Невозможность найти элемент – одна из главных причин нестабильности автотестов. При поиске элементов часто могут возникать проблемы. Когда мы пытаемся найти элемент, мы делаем предположение о состоянии нашего приложения. Но ожидаемые и фактические результаты могут как совпадать, так и расходиться друг с другом.

exception когда Appium не может найти нужный элемент
Когда Appium не может найти нужный элемент, в нашем коде будет сгенерировано исключение NoSuchElementException.

Мы должны стараться избегать потенциальных проблем, таких как:

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

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

accessibility id
driver.find_element(AppiumBy.ACCESSIBILITY_ID, "foobarbaz")

Стратегии локаторов

Что мы понимаем под нахождением элементов  и accessibility id? В Appium (как и в Selenium) действия могут производиться над определенными объектами пользовательского интерфейса приложения. Эти объекты (соответствующие элементам на веб-странице, отсюда и название команды в API find_element) должны быть найдены прежде чем с ними можно будет взаимодействовать. Существуют различные способы поиска элементов.

Стратегии локаторов в Appium
Стратегии локаторов в Appium

Class Name

Посмотрим на пример вызова, приведенный ниже:

локаторы и селекторы
driver.find_element(AppiumBy.CLASS_NAME, "button")

В данном примере  AppiumBy.CLASS_NAME представляет собой стратегию локатора под названием Class Name, а button представляет собой селектор. Эта стратегия используется для поиска одного или нескольких элементов. Результатом этого вызова – если все прошло успешно – является объект типа WebElement, для которого существует множество методов для взаимодействия в API, на которые мы полагаемся при нашем тестировании.

Class Name – это одна из нескольких стратегий локатора, доступных в Appium, которая ссылается на имя класса объекта в UI, различающегося для конкретной платформы, например XCUIElementTypeButton или android.widget.Button. Такая стратегия использования локаторов не является оптимальной для тестирования кроссплатформенного приложения. Для поиска кнопки на iOS или на Android нам будет необходим разный код.

преимущества class name в appium

Также, есть еще одна проблема, связанная с этой стратегией. Часто бывает ситуация, когда в разметке имеется более одного элемента заданного типа. И получается, что мы сможем найти кнопку с помощью такого локатора, но это может быть не та кнопка, которая нам нужна. Поэтому, стратегия локатора Class Name не является оптимальным выбором, поскольку она зависима от платформы (приводит к разветвленному коду для iOS и Android) и является слишком общей (трудно однозначно идентифицировать элемент).

Все стратегии локаторов

Какие еще существуют варианты локаторов? Вот их полный список:

все стратегии локаторов

Многие локаторы были перенесены из Selenium, хотя не все они поддерживаются или даже нужны в Appium (по крайней мере, при автоматизации нативных приложений). Appium также добавил ряд собственных стратегий, таких как accessibility id, чтобы учесть особенности (и использовать их преимущества), связанные с UI мобильных приложений и использованием совершенно иного стека автоматизации.

кросс-платформенные и уникальные локаторы для appium

XPath

преимущества и недостатки xpath в appium

Вот краткое описание стратегии локатора XPath и причин, по которым ее следует избегать:

  • XPath может быть привлекательной стратегией для локаторов, поскольку она основана на разметке, то есть может найти любой элемент в DOM или в структуре мобильных приложений.
  • XPath можно легко использовать для поиска элемента с селектором по типу //*[1]/*[1]/*[3]/*[2]/*[1]/*[1], особенно если нет другого способа найти этот элемент.
  • Однако полагаться на такой селектор – плохая идея, поскольку он может перестать работать при любом изменении в структуре приложения. Это связано с тем, что структура приложений обычно непостоянная и может меняться между запусками или версиями приложения.
  • При использовании драйвера XCUITest работа с XPath может быть очень медленной. Это связано с тем, что каждый раз при выполнении XPath-запроса необходимо рекурсивно пройти по всей структуре приложения и преобразовать ее в формат XML, что может занять много времени, особенно если приложение содержит много элементов.
  • Даже если мы избежим типичных подводных камней XPath, применяя более надежные и точные селекторы, мы все равно потратим много времени вначале на генерацию XML-документа.
  • Решение состоит в том, чтобы либо не использовать XPath, либо использовать его с умом. Если мы можем получить прямой доступ к элементу с помощью id, name или accessibility id, то лучше в первую очередь использовать их.

Если с элементом не связан уникальный id или label, а с XPath получается слишком медленно, рассмотрите возможность использования стратегий локаторов -ios predicate string или -ios class chain.

Кроссплатформенные стратегии локаторов

Accessibility id

Вместо стратегий локаторов, описанных выше, лучше использовать стратегию accessibility id, поскольку она:

а) кроссплатформенная; 

б) уникальная;

в) быстрая. 

Если accessibility id одинаковы в обеих версиях нашего приложения, то мы можем использовать один и тот же код в Appium для поиска элемента вне зависимости от платформы.

Этот локатор соответствует метке (label), которую разработчики присваивают элементам  приложения в целях обеспечения доступности (accessibility). Понятие метки доступности есть и в iOS, и в Android, однако в iOS она называется Accessibility id, а в Android – Content Description  (или content-desc).

accessibility id для ios и android

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

В Python клиенте Appium поиск элементов по идентификатору доступности осуществляется с помощью стратегии AppiumBy:

appiumby
el = driver.find_element(AppiumBy.ACCESSIBILITY_ID, "foobarbaz")

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

Стратегии локаторов, уникальные для платформы

Стратегии локаторов для iOS

Некоторые стратегии локаторов для iOS могут быть использованы в качестве замены XPath, так как они основаны на иерархических запросах. Наиболее надежной стратегией является -ios class chain, которая позволяет нам использовать “облегченную” версию чего-то вроде XPath, смешанную со строками предикатами для iOS.

Преимущество этой стратегии локаторов заключается в том, что она позволяет выполнять сложные запросы, при этом в большинстве случаев значительно превосходя XPath по скорости. Недостатком, конечно же, является то, что она работает только для конкретной платформы. Это требует разделения кода для кроссплатформенного теста (или добавления дополнительных различий в наши модели объектов). В качестве примера такого локатора, можно привести следующую команду.

Пример iOS Class Chain.

ios class chain
driver.find_element(AppiumBy.IOS_CLASS_CHAIN, "**/XCUIElementTypeCell[`name BEGINSWITH "C"`]/XCUIElementTypeButton[10]")

В примере выше мы пытаемся найти 10-ю кнопку, которая является дочерним элементом ячейки таблицы где-либо в структуре UI и имеет имя, начинающееся с символа “C”. Это довольно сложный запрос. Благодаря более строгой форме запросов Class Chain, такой вид локаторов более производительный, чем XPath.

Пример строки предиката для iOS.

appium ios predicate
driver.find_element(AppiumBy.IOS_PREDICATE, "type == 'XCUIELementTypeButton' AND value BEGINSWITH[c] 'foo' AND visible == 1")

Стратегии локаторов для Android

Аналогичный прием доступен и для Android в виде специального парсера в Appium, который поддерживает большую часть UiSelector API. Этот парсер доступен через локатор -android uiautomator. Селекторы должны быть строками, состоящие из фрагментов Java-кода, начинающиеся с new UiSelector(). Рассмотрим следующий пример:

Пример UiAutomator для Android.

android uiautomator
driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().className("ScrollView").getChildByText(new UiSelector().className("android.widget.TextView"), "Tabs")')

В очередной раз мы используем AppiumBy, поскольку этот способ доступен только для Appium. В данном случае мы сконструировали строку, которую можно использовать в качестве валидного кода UiAutomator, но на самом деле Appium ее распарсит и преобразует при отправке команды. Согласно семантике UiSelector API, мы говорим, что нам нужен первый элемент TextView с текстом “Tabs”, который также является дочерним элементом первого ScrollView в разметке. Этот метод более громоздкий, чем XPath, но его можно использовать схожим образом, и, опять же, он будет производительнее в большинстве случаев.

Как и в случае со стратегией iOS Class Chain, основным недостатком здесь является то, что селекторы будут привязаны к конкретной платформе. Кроме того, Appium не поддерживает произвольный Java, существуют ограничения в том, что они могут предоставить через API UiSelector.

Поиск селекторов

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

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

способы поиска селекторов в appium

Через исходный код приложения

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

appium page_source
print(driver.page_source)

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

xml ui appium
XML-документ, в котором содержится структура UI на момент запроса исходного кода страницы.

Это XML-документ, в котором содержится структура пользовательского интерфейса на момент запроса кода страницы. Каждый элемент, который доступен Appium, представлен здесь в виде XML-элемента. Поэтому если мы не нашли нужный нам элемент тут, то и Appium не сможет найти его.

xml ui appium

Просмотр вывода XML также полезен для поиска селекторов XPath, поскольку, когда мы выполняем XPath-запрос, мы обращаемся именно сюда. Мы можем просмотреть этот XML и понять, каким может быть хороший XPath-запрос для нужного нам элемента, который мы хотим найти с помощью Appium.

Мы также можем узнать все атрибуты, которые содержит элемент, и их значения с помощью кода, используя метод element.get_attribute().

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

Appium Inspector

Теперь попробуем вторую, наиболее удобную стратегию поиска селекторов – Appium Inspector. Он позволяет исследовать структуру приложения с помощью интерфейса “point-and-click”.

Для автоматизации, нам необходимо знание исходного кода приложения. Как мы можем получить эти знания? Если мы один из разработчиков приложения, мы можем просто посмотреть код или вспомнить, что мы присвоили определенному элементу определенную метку accessibility. Если же у нас нет доступа к коду или нам нужен метод, который покажет нам, что именно видит Appium в нашем приложении, то лучше всего использовать Appium Inspector.

Appium Inspector – это GUI-клиент для запуска Appium и исследования приложений. С его помощью мы можем запускать сессию инспектора  с выбранными параметрами. С помощью него мы видим скриншот нашего приложения, структуру интерфейса (в виде XML) и множество метаданных о любом элементе, который мы выбираем. Выглядит это следующим образом:

интерфейс Appium Inspector
Appium Inspector

Одна из особенностей инспектора заключается в том, что, когда мы щелкаем по элементу в разметке, он подсказывает нам стратегии локаторов и селекторы. На изображении выше мы видим, что на самом верху из предложенных стратегий локаторов стоит accessibility id, используемая в сочетании с селектором Login Screen.

Appium Inspector существует в двух форматах:

  1. В виде десктопного приложения для macOS, Windows и Linux. Последнюю версию можно скачать в разделе Releases его репозитория. Найдите версию для вашей ОС и установите ее.
  2. В виде веб-приложения. На текущий момент, у такой версии есть известная проблема – она не работает в Safari. Также убедитесь, что сервер Appium запущен с параметром --allow-cors, чтобы разрешить браузеру CORS.

Смотрите также: “Руководство по установке и использованию Appium”

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

Конечно, могут быть различные сложные сценарии, с которыми мы столкнемся, но инспектор –  это всегда отличный способ, чтобы разобраться в структуре нашего приложения. Он может быть особенно полезен, если у нас возникают проблемы с поиском элемента на определенной странице. В таком случае можно открыть инспектор и вручную просмотреть дерево XML, чтобы убедиться, что элемент действительно существует. Если его нет, значит, Appium (читай: базовый фреймворк автоматизации) его не видит, и нужно спросить разработчика приложения, в чем может быть проблема.

Заключение

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

Удачного тестирования!

Перевод статьи «Finding Mobile Elements with Robust Appium Locator Strategies and Selectors».

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *