[Разработка под iOS, Swift, Тестирование мобильных приложений] Погружение в автотестирование на iOS. Часть 2. Как взаимодействовать с ui-элементами iOS приложения в тестах
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Привет, Хабр!В прошлой статье мы разобрались:
- Что такое ui-тесты и для чего они нужны;
- Как настроить окружение для тестов;
- Как находить ui-элементы в проекте и проставлять им accessibilityidentifier.
В этой статье мы разберем:
- Как обращаться и инициализировать ui-элементы в ваших тестах;
- Как взаимодействовать с ui-элементами приложения;
- Как писать ассерты для проверки в автотесте ожидаемого результата.
Как обращаться и инициализировать 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.Взаимодействие с UISliderUISlider — это элемент управления для выбора одного значения из диапазона значений.
Когда мы хотим изменить положение ползунка в слайдере, мы не передаем значение, которое хотим установить. Вместо этого мы выбираем число в диапазоне от 0 до 1. Где 0 — это минимальное значение в слайдере, а 1 — максимальное. Представим, что у нас есть слайдер с максимальным значением 100 и нам нужно сдвинуть ползунок на значение 25. Это будет выглядеть так:
XCUIApplication().sliders.element.adjust(toNormalizedSliderPosition: 0.25)
Взаимодействие с UIPickerView и UIDatePickerUIPickerView и 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 BarNavigation 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 barTab 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 (например запуск сафари, документов и так далее);
- И многое другое.
===========
Источник:
habr.com
===========
Похожие новости:
- [Анализ и проектирование систем, IT-инфраструктура, Nginx, Mesh-сети, DevOps] Зачем нужен обратный прокси сервер в 5 актах
- [Исследования и прогнозы в IT, Искусственный интеллект, IT-компании] Как выстроить процесс интеллектуальной обработки документов с помощью RPA: опыт UiPath
- [Разработка под iOS, Обработка изображений, Машинное обучение, Разработка под AR и VR] А ну-ка, сгруппировались, или как отделить фото котиков от счетов ЖКХ
- [API, ERP-системы, Управление разработкой, Управление проектами, Будущее здесь] Digital-трансформация завода: CRM для ERP, роботизация БП и оживление железа, ЛК, чат-боты и dream team (ч. 2)
- [Высокая производительность, Хранение данных, Компьютерное железо, Накопители, Настольные компьютеры] GOODRAM IRDM Pro gen.2: терабайтный SSD с приличными скоростями
- [Высокая производительность, Amazon Web Services, Microsoft Azure, Google Cloud Platform, Облачные сервисы] Cockroach Labs провела тесты облачных провайдеров
- [Разработка под iOS, Разработка мобильных приложений, Swift] Vivid UI
- [Разработка под iOS, Swift] Делаем свой Widget в iOS 14
- [Разработка под iOS, Разработка под MacOS] Apple заблокировала установку iOS-приложений на Mac с чипом M1 через сторонние сервисы
- [Разработка под iOS, Разработка мобильных приложений, Голосовые интерфейсы] Как мы интегрировали Яндекс.Музыку с Siri. Доклад Яндекса
Теги для поиска: #_razrabotka_pod_ios (Разработка под iOS), #_swift, #_testirovanie_mobilnyh_prilozhenij (Тестирование мобильных приложений), #_ios, #_testirovanie (тестирование), #_avtomatizatsija (автоматизация), #_mobile_testing, #_qa, #_mobile_automation, #_qa_automation, #_xcuitest, #_blog_kompanii_vivid_money (
Блог компании Vivid Money
), #_razrabotka_pod_ios (
Разработка под iOS
), #_swift, #_testirovanie_mobilnyh_prilozhenij (
Тестирование мобильных приложений
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:07
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Привет, Хабр!В прошлой статье мы разобрались:
XCUIApplication().buttons["Help"]
// Находит все кнопки внутри 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 let moneyTitle: XCUIElement = XCUIApplication().staticTexts["accessibilityID"]
// Совершаем нажатие на 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")
// Совершаем нажатие двумя пальцами на ui-элемент
XCUIApplication().buttons.element.twoFingerTap() /* Совершаем нажатие на элемент столько раз сколько передали в withNumberOfTaps и столькими "пальцами" сколько передали в numberOfTouches */ XCUIApplication().buttons.element.tap(withNumberOfTaps: 1, numberOfTouches: 1) // Совершаем свайп в указанном направлении
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) Когда мы хотим изменить положение ползунка в слайдере, мы не передаем значение, которое хотим установить. Вместо этого мы выбираем число в диапазоне от 0 до 1. Где 0 — это минимальное значение в слайдере, а 1 — максимальное. Представим, что у нас есть слайдер с максимальным значением 100 и нам нужно сдвинуть ползунок на значение 25. Это будет выглядеть так: XCUIApplication().sliders.element.adjust(toNormalizedSliderPosition: 0.25)
XCUIElement имеет специальный метод для взаимодействия с UIPickerView и UIDatePicker:
// Пикер с одним колесом
XCUIApplication().pickerWheels.element.adjust(toPickerWheelValue: "BMW") // Пикер с несколькими колесами XCUIApplication().pickerWheels.elementBoundByIndex(0).adjust(toPickerWheelValue: "BMW") XCUIApplication().pickerWheels.elementBoundByIndex(1).adjust(toPickerWheelValue: "X6") Чтобы взаимодействовать с ним, вам понадобится использовать метод addUIInterruptionMonitor(withDescription:handler:)Где вы передаете:
addUIInterruptionMonitor(withDescription: "Current Location Not Available") { alert in
alert.buttons["OK"].tap() return true } Представим, что у нас есть две кнопки и текст по середине в 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. // Открываем первую вкладку
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")
=========== Источник: habr.com =========== Похожие новости:
Блог компании Vivid Money ), #_razrabotka_pod_ios ( Разработка под iOS ), #_swift, #_testirovanie_mobilnyh_prilozhenij ( Тестирование мобильных приложений ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 21:07
Часовой пояс: UTC + 5