Погружение в автотестирование на iOS. Часть 2. Как взаимодействовать с ui-элементами iOS приложения в тестах

Привет, Хабр!

В прошлой статье мы разобрались:

  • Что такое ui-тесты и для чего они нужны;

  • Как настроить окружение для тестов;

  • Как находить ui-элементы в проекте и проставлять им accessibilityidentifier.

В этой статье мы разберем:

  1. Как обращаться и инициализировать ui-элементы в ваших тестах;

  2. Как взаимодействовать с ui-элементами приложения;

  3. Как писать ассерты для проверки в автотесте ожидаемого результата.

Как обращаться и инициализировать ui-элементы

При наличии айдишника у ui-элемента, достаточно указать его при обращении.

XCUIApplication().buttons["Help"]

Если же у вас нет id у элемента, есть способ найти его при помощи XCUIElementQuery. Этот класс позволяет искать элемент несколькими способами.

// Находит все кнопки внутри scroll view (отобразит кнопки только прямого потомка scroll view)
XCUIApplication().scrollViews["Main"].children(matching: .button)

// Находит все кнопки внутри scroll view (отобразит кнопки прямого потомка scroll view, но также и его потомков)
XCUIApplication().scrollViews["Main"].descendants(matching: .button)    

// Находит четвертую кнопку на экране
XCUIApplication().buttons.element(boundBy: 3)

// Находит в scroll view ui-элемент содержащий label = identifier
XCUIApplication().scrollViews["Main"].containing(NSPredicate(format: "label == %@","identifier").element

// Находит первую кнопку на экране
XCUIApplication().buttons.firstMatch

Немного про NSPredicate — это класс, который позволяет фильтровать объекты по нужному вам условию. Статья с хорошим объяснением как использовать NSPredicate.

Пример иницилизации переменной:

let moneyTitle: XCUIElement = XCUIApplication().staticTexts["accessibilityID"]

Взаимодействия с ui-элементами приложения

Нажатие и удержание

Вы можете в своих тестах совершать: нажатие, удержание и drag&drop ui-элементов.

Перечень методов можно посмотреть здесь, раздел — Tapping and Pressing.

// Совершаем нажатие на ui-элемент
XCUIApplication().buttons.element.tap()

// Cовершаем двойное нажатие на ui-элемент
XCUIApplication().buttons.element.doubleTap()

// Удерживаем нажатие в течение времени, которое передали в forDuration
XCUIApplication().buttons.element.press(forDuration: 3)

// Совершаем нажатие на ui-элемент и затем перетаскиваем его к другому ui-элементу
XCUIApplication().buttons.element.press(forDuration: 3, thenDragTo: XCUIApplication().searchFields.element)

Ввод текста

Вы можете вводить текст по букве обращаясь к системной клавиатуре:

XCUIApplication().textFields.element.tap()
XCUIApplication().keys["h"].tap()
XCUIApplication().keys["e"].tap()
XCUIApplication().keys["l"].tap()
XCUIApplication().keys["p"].tap()

Либо вводить целую строку:

XCUIApplication().textFields.element.typeText("help")

Информация по методу typeText

Множественные нажатия

Вы можете совершать множественные нажатия в своих тестах.

// Совершаем нажатие двумя пальцами на ui-элемент
XCUIApplication().buttons.element.twoFingerTap()

/*
     Совершаем нажатие на элемент столько раз сколько передали
     в withNumberOfTaps и столькими "пальцами" сколько передали
     в numberOfTouches
*/
XCUIApplication().buttons.element.tap(withNumberOfTaps: 1, numberOfTouches: 1)

Перечень методов можно посмотреть здесь, раздел — Multiple Taps.

Жесты

Вы можете совершать разные жесты в своих тестах.

// Совершаем свайп в указанном направлении
swipeLeft()
swipeRight()
swipeUp()
swipeDown()

// Совершаем свайп в указанном направлении с заданной скоростью
swipeLeft(velocity: 0.5)
swipeRight(velocity: 0.5)
swipeUp(velocity: 0.5)
swipeDown(velocity: 0.5)

// Совершаем приближения ui-элемента (withScale указываем больше 1)
XCUIApplication().images.element(boundBy: 0).pinch(withScale: 2, velocity: 1) 
// Совершаем отдаления ui-элемента (withScale указываем от 0 до 1)
XCUIApplication().images.element(boundBy: 0).pinch(withScale: 0.5, velocity: 1)

// Совершаем вращение ui-элемента
XCUIApplication().images.element(boundBy: 0).rotate(0.5, withVelocity: 0.5)

Перечень методов можно посмотреть здесь, раздел — Performing Gestures.

Взаимодействие с UISlider

UISlider — это элемент управления для выбора одного значения из диапазона значений.

Когда мы хотим изменить положение ползунка в слайдере, мы не передаем значение, которое хотим установить. Вместо этого мы выбираем число в диапазоне от 0 до 1. Где 0 — это минимальное значение в слайдере, а 1 — максимальное. Представим, что у нас есть слайдер с максимальным значением 100 и нам нужно сдвинуть ползунок на значение 25. Это будет выглядеть так:

XCUIApplication().sliders.element.adjust(toNormalizedSliderPosition: 0.25)

Взаимодействие с UIPickerView и UIDatePicker

UIPickerView и UIDatePicker — это ui-элементы, которые используют “колесики” для выбора необходимых значений.

XCUIElement имеет специальный метод для взаимодействия с UIPickerView и UIDatePicker:

  • Для пикеров с одним колесом, мы можем получить доступ через element(), и указать значение, которое хотим выбрать;

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

// Пикер с одним колесом
XCUIApplication().pickerWheels.element.adjust(toPickerWheelValue: "BMW")

// Пикер с несколькими колесами
XCUIApplication().pickerWheels.elementBoundByIndex(0).adjust(toPickerWheelValue: "BMW")
XCUIApplication().pickerWheels.elementBoundByIndex(1).adjust(toPickerWheelValue: "X6")

Взаимодействие с системным алертом

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

Чтобы взаимодействовать с ним, вам понадобится использовать метод addUIInterruptionMonitor(withDescription:handler:)

Где вы передаете:

  • withDescription — заголовок алерта;

  • handler – действие, которое хотите совершить.

Пример использования в тестах:

addUIInterruptionMonitor(withDescription: "Current Location Not Available") { alert in
    alert.buttons["OK"].tap()
    return true
}

Взаимодействие с Navigation Bar

Navigation bar — это панель навигации, отображается в верхней части экрана приложения под status bar и позволяет перемещаться по приложению.

Представим, что у нас есть две кнопки и текст по середине в Navigation Bar.

Вот пример того как можно их иницилизировать и в дальнейшем с ними взаимодействовать:

// Иницилизируем крайнюю левую кнопку в Navigation bar 
let leftNavBarButton = XCUIApplication().navigationBars.children(matching: .button).firstMatch

// Иницилизируем тест посередине в Navigation bar 
let topicNavBar = XCUIApplication().navigationBars.children(matching: .staticTexts).firstMatch

// Иницилизируем крайнюю правую кнопку в Navigation bar
let rightNavBarButton = XCUIApplication().navigationBars.children(matching: .button).element(boundBy: 1)

// Нажимаем на кнопки в Navigation bar 
leftNavBarButton.tap()
rightNavBarButton.tap()

// Проверяем заголовок в Navigation bar 
XCTAssertEqual(topicNavBar.title, "Topic")

Взаимодействие с Tab bar

Tab bar — это панель вкладок, отображается в нижней части экрана приложения. Она даёт возможность быстро переключаться между различными разделами приложения.

Для переключения между вкладками достаточно тапать на индекс элемента в Tab bar.

// Открываем первую вкладку 
XCUIApplication().tabBars.buttons.element(boundBy: 0)
// Открываем третью вкладку
XCUIApplication().tabBars.buttons.element(boundBy: 2)

Создание ассертов:

Ассерты — это проверки необходимого условия.

Рассмотрим несколько вариантов их использования:

// Ассерт, что кнопка отображается на экране
XCTAssertTrue(XCUIApplication().buttons["Warning"].exists)

// Ассерт, что кнопка не выделена
XCTAssertFalse(XCUIApplication().buttons["Warning"].isSelected)

// Ассерт, что title кнопки равен - Buy
XCTAssertEqual(XCUIApplication().buttons.element.title, "Buy")

// Ассерт, что placeholder в textFields не равен - placeHolder
XCTAssertNotEqual(XCUIApplication().textFields.element.placeholderValue, "placeHolder")

// Ассерт, что value в textFields равно - value
XCTAssertEqual(XCUIApplication().textFields.element.value, "value")

Полный перечень возможных ассертов можно посмотреть здесь, раздел Test Assertions

Перечень возможных атрибутов ui-элементов можно посмотреть здесь

Заключение:

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

В следующей статье мы расскажем про жизненый цикл тестового приложения:

  • Как делать предусловия и послеусловия;

  • Как сбрасывать статус пермишенов приложения перед запуском тестов (доступ к галерее, фото и так далее);

  • Как запускать приложения по bundle identifier (например запуск сафари, документов и так далее);

  • И многое другое.

Let’s block ads! (Why?)

Read More

Recent Posts

Роскомнадзор рекомендовал хостинг-провайдерам ограничить сбор данных с сайтов для иностранных ботов

Центр управления связью общего пользования (ЦМУ ССОП) Роскомнадзора рекомендовал компаниям из реестра провайдеров ограничить доступ поисковых ботов к информации на российских сайтах.…

15 часов ago

Apple возобновила переговоры с OpenAI и Google для интеграции ИИ в iPhone

Apple возобновила переговоры с OpenAI о возможности внедрения ИИ-технологий в iOS 18, на основе данной операционной системы будут работать новые…

5 дней ago

Российская «дочка» Google подготовила 23 иска к крупнейшим игрокам рекламного рынка

Конкурсный управляющий российской «дочки» Google подготовил 23 иска к участникам рекламного рынка. Общая сумма исков составляет 16 млрд рублей –…

6 дней ago

Google завершил обновление основного алгоритма March 2024 Core Update

Google завершил обновление основного алгоритма March 2024 Core Update. Раскатка обновлений была завершена 19 апреля, но сообщил об этом поисковик…

6 дней ago

Нейросети будут писать тексты объявления за продавцов на Авито

У частных продавцов на Авито появилась возможность составлять текст объявлений с помощью нейросети. Новый функционал доступен в категории «Обувь, одежда,…

6 дней ago

Объявлены победители международной премии Workspace Digital Awards-2024

24 апреля 2024 года в Москве состоялась церемония вручения наград международного конкурса Workspace Digital Awards. В этом году участниками стали…

6 дней ago