Привет, меня зовут Сергей и я SDET-специалист в IT-компании SimbirSoft. В своей практике мне приходится тестировать как веб-, так и мобильные приложения на Android. Особенность тестирования мобилок в том, что шаги автотеста нужно максимально приблизить к действиям пользователя. О чем это я? Да все о том же — на смартфонах не кликают, а тапают; не закрывают по крестику модалки, а свайпают. Это как на флоте, эти все словечки понятны только тем, кто драил гальюн или бакланил из камбуза хлеб. 

В этой статье рассмотрим несколько методов скроллов класса TouchAction инструмента Appium, которые позволяют скроллить до нужного элемента или проверить свайп модального окна. И несмотря на то, что в новой версии Appium используются методы executeScript(), класс TouchAction все еще актуален. Поэтому я рекомендую к прочтению эту статью, в первую очередь, тем, кто использует в своих проектах Appium.

Что такое Appium?

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

Продукт позволяет реализовать кросс-платформенное тестирование приложений. С помощью Appium тестировщик может писать универсальные тесты на едином языке программирования, остальное делает инструмент — переводит запросы на язык драйверов.

Термины

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

Tap — касание, нажатие на сенсорный экран. Чтобы открыть любое приложение на смартфоне, мы тапаем на его иконку.

Action menu — кнопка, которая представляет собой три точки, и при тапе на нее открывается меню с несколькими action’ами.

Tab — вкладка. Обычно переключение между табами осуществляется тапом на нужный таб или смахивание (свайпом) вправо/влево.

Page Controls — элемент управления, который отображает текущее положение экрана в плоском списке страниц (на скринах — точки над кнопкой, отображающие текущее положение через изменение цвета).

Suggest List — выпадающий список, состоящий из подсказок; появляется при вводе букв, слов или символов в поле ввода. Или список ранее совершенных поисковых запросов. Отдельный пункт из этого списка — Suggest.

Slider — горизонтальная шкала с элементом управления, по которой скольжением пальца можно управлять состоянием или значением характеристики (в нашем случае — расстоянием от указанного адреса):

Scroll — вертикальное пролистывание содержимого, когда скользят пальцем по экрану сверху вниз или снизу вверх.

Swipe — смахивание вниз, вверх, вправо или влево. Похоже на скролл, только с «легким», коротким касанием.

Ну вот в основных понятиях мы разобрались. Далее в статье расскажу, как настроить автоматизацию тестирования приложения на Android с реальными действиями пользователя. А также как реализовать скролл.

Практика

1 шаг: Скачать Appium-Python-Client, который поможет нам общаться с эмулятором.

2 шаг: Скачать Android Studio для создания эмулятора.

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

3 шаг: Для написания тестов нужно выбрать инструмент для взаимодействия с POM и написания локаторов для элементов тестируемого приложения. Можно использовать как selenium, так и упрощенную версию selene. Данные библиотеки импортируются стандартно через pip.

pip install selene

pip install selenium

Более подробно о различных инструментах автоматизации тестирования мобильных приложений можно почитать здесь. 

А о том, как настроить и развернуть окружение для тестирования можно узнать из этой статьи.

Далее рассмотрим, как на практике реализовать некоторые виды скроллов.

Скролл по координатам

Данный тип скролла использует принцип перемещения от одной точки к другой. Экран приложения условно разбивается по точкам координат по (X, Y). Начальная точка расположена в верхнем левом углу экрана (0, 0). Такой метод можно использовать, если заранее известны координаты расположения элементов или нужен скролл от элемента к элементу.

def scroll_by_points(self, start_point, end_point, duration_long_press=2000) -> None:
	 action = TouchAction(self.driver)
	action.long_press(x=start_point[0], y=start_point[1], duration=duration_long_press)
	action.move_to(x=end_point[0], y=end_point[1])
	action.release()
	action.perform()

Функция scroll_by_points():

  • start_point — пара X, Y координат для начала скролла. Используется кортеж.

  • end_point — пара X, Y координат для окончания скролла.

  • duration — продолжительность удержания тапа, целое число в млс.

  • long_press() — метод класса TouchAction, начинает цепочку действий скролла, продолжительность указывается в миллисекундах.

  • move_to() — метод класса TouchAction, перемещает указатель на следующую точку

  • release() — метод класса TouchAction, завершает действие, подняв указатель от экрана.

  • perform() — метод класса TouchAction, пересылает команду серверу для выполнения скролла

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

Минусы: этот метод не адаптивен для разных размеров экранов. При изменении размера скролл может не докрутить до нужного элемента или остановиться на половине какой-нибудь картинки.

Вертикальный скролл (вверх-вниз)

Такой скролл используется при прокрутке экрана вниз или вверх. Чаще всего он встречается в новостной ленте или при просмотре фото/видео в соцсетях.

def scroll_vertical_up(self) -> None:
	window = self.driver.get_window_size()
	x = window.get("width")
	y = window.get("height")
	self.scroll_by_points((int(x / 2), int(y * 0.5)), (int(x / 2), int(y * 0.85)))

def scroll_vertical_down(self) -> None:
	window = self.driver.get_window_size()
	x = window.get("width")
	y = window.get("height")
	self.scroll_by_points((int(x / 2), int(y * 0.85)), (int(x / 2), int(y * 0.5)), 300)

Функция scroll_vertical_up(down):

  • driver.get_window_size— возвращает размер экрана

  • window.get(“width”) — возвращает ширину экрана

  • window.get(“height”) — возвращает высоту экрана

Далее используем скролл по координатам, где значение по координате X — постоянная величина. В нашем примере — это середина экрана. По координате Y в качестве начала скролла указываем точку, близкую к нижней части экрана, а в качестве конечной точки указываем середину экрана. Получается скролл от нижней части к середине экрана. Если значение Y в кортеже конечной точке умножить, к примеру, на 0,1 или 0,2, то скролл будет более длинным.

Горизонтальный скролл (влево-вправо)

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

def scroll_horizontal_right(self) -> None:
	 window = self.driver.get_window_size()
	x = window.get("width")
	y = window.get("height")
	self.scroll_by_points((int(x * 0.85), int(y / 2)), (int(x * 0.5), int(y / 2)))

def scroll_horizontal_left(self) -> None:
	 window = self.driver.get_window_size()
	x = window.get("width")
	y = window.get("height")
	self.scroll_by_points((int(x * 0.15), int(y / 2)), (int(x * 0.5), int(y / 2)))

Функция scroll_horizontal_right(left) использует базовый скролл по координатам, только теперь изменяется значение по оси X. Затем, используя процентное соотношение по экрану, можно приблизительно указать первоначальную и конечную точку скролла.

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

Скролл от элемента к элементу

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

Скролл осуществляется по координатам объектов. В начале нужно определить координаты элемента, к которому нам нужно переместить следующий элемент. Затем определяем координаты элемента, который будем «притягивать» к первому. Используя метод скролла по координатам, перемещаем наш объект в нужном направлении. Такой метод можно использовать как для вертикального, так и горизонтального скролла.

def scroll_from_element_to_element(self, start_element_locator, end_element_locator):
	start_element_location = self.get_element_location(start_element_locator)
	end_element_location = self.get_element_location(end_element_locator)
	start_point = (start_element_location["x"], start_element_location["y"])
	end_point = (end_element_location["x"], end_element_location["y"])
	self.scroll_by_points(start_point, end_point)

Функция scroll_from_element_to_element():

  • start_element_location, end_element_location — для локации элементов используется метод для определения точки координат X, Y элемента в качестве первоначальной и конечной точки скролла.

  • start_point, end_point — координаты точек вектора движения скролла, эти точки будут соответствовать координатам начального элемента и конечного.  

Скролл до искомого элемента

Иногда приходится использовать скролл до нужного элемента. Например, необходимо скроллить экран до новости, которую затем необходимо проверить. Для этого можно использовать скролл до тех пор, пока элемент не будет отображаться на экране. Для такого скролла возможно использовать различные библиотеки для поиска локатора и взаимодействием с DOM как на web, так и android. Для примера используем selene.

def scroll_up_to_element(self, locator):
	while not locator.matching(be.visible):
		self.scroll_vertical_up()

Функция scroll_up_to_element():

  • locator — функция принимает в качестве аргумента локатор искомого элемента

  • используем цикл while, условием которого будет проверяться видимость локатора в DOM. Чтобы цикл не зациклился в бесконечный скролл, можно установить ограничения по времени.

  • пока условие True, используя функцию вертикального скролла вверх, будет прокручивание экрана до видимости элемента на экране. 

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

Drag&Drop

Это интуитивно понятный механизм перемещения данных внутри пользовательского интерфейса. В переводе с английского его название буквально значит «Тащи-и-бросай». Он позволяет повысить удобство работы пользователя и увеличить скорость обработки данных.

ef drag_and_drop(self, locator_element, start_point, end_point):
	actions = TouchAction(driver)
	actions.long_press(locator_element)
	actions.move_to(start_point, end_point)
	action.release()
	action.perform()

Функция drag_and_drop():

  • locator — функция принимает в качестве аргумента локатор искомого элемента.

  • long_press — метод класса TouchAction который имитирует захват элемента на экране.

  • move_to — метод перемещения элемента по координатам.

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

Свайпы (смахивания)

Хочу заметить, что в документации appium нет информации о том, как реализована данная функциональность. Принцип смахивания и запуска «карусели» заключается в быстром движении пальца по экрану — рывка. На программном уровне за это отвечает класс Scroller

public class Scroller extends Object

В документации написано, что этот класс инкапсулирует прокрутку. Можно использовать скроллеры (Scroller или OverScroller) для сбора данных, необходимых для создания анимации прокрутки, например, в ответ на жест рывка. Скроллеры отслеживают смещения прокрутки с течением времени, но они не применяют эти позиции автоматически к представлению и несут ответственность за получение и применение новых координат с такой скоростью, которая сделает анимацию прокрутки плавной.

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

Подведем итог

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

P.S. Гифки сделал сам ;)

Спасибо за внимание!

Больше авторских материалов для SDET-специалистов от моих коллег читайте в соцсетях SimbirSoft — ВКонтакте и Telegram.

Комментарии (1)


  1. m_aleksei
    20.11.2024 11:04

    Зачем писать TouchAction который уже 2+ года не используется?