[Разработка под iOS, Swift, Тестирование мобильных приложений] Погружение в автотестирование на iOS. Часть 4. Ожидания в XCUITest
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Привет, Хабр!В UI тестах не все события происходят синхронно друг за другом. Сетевые запросы, анимации, чтение файлов – все это требует времени. Встает вопрос – как заставить тест ждать наступления определенного события?В этой статье мы разберем:
- Что такое ожидание и для чего они используются в тестах;
- Рассмотрим какие бывают ожидания;
- Разберем из чего состоят ожидания;
- Рассмотрим пример эффективных ожиданий в тестах.
Что такое ожидание и для чего они используются в тестахОжидания — это методы, которые ждут выполнения определенного условия или истечения определенного времени. Так как элементы на экране появляются не всегда моментально, нам необходимо использовать задержки иначе код отвечающий за действия не будет работать, потому что элемента ещё нет на экране.Ожидания бывают двух типов:
- Явные ожидания;
- Неявные ожидания.
Разберем подробно каждый тип.Явные ожиданияЯвные ожидания — это код, который ждет наступления какого-то события, прежде чем продолжит выполнение команды скрипта. Такое ожидание срабатывает один раз в указанном месте.Пример:
// Ждем 5 секунд
Thread.sleep(forTimeInterval: 5)
Сразу скажу, что использование явных ожиданий — это моветон в автоматизации. Использование явных задержек не гарантирует наступление нужного события. Или будет слишком избыточным и увеличит время выполнения теста.Неявные ожидания Неявные ожидания — это код, который делает многократные попытки найти элемент на экране в течение заданного периода времени, если элемент не найден сразу.Пример:
// Ждём в течении 5 секунд что кнопка есть на экране. Если кнопка отобразится на 2 секунде, ожидание выполнится и мы пойдем дальше
let element = XCUIApplication().buttons["testButton"]
let predicate = NSPredicate(format: "exists == true")
let expectation = XCTNSPredicateExpectation(predicate: existsPredicate,
object: element)
wait(for: [expectation], timeout: 5)
Условия выполнения ожиданияПрежде чем написать ожидание, мы должны создать условия выполнения этого ожидания. В этом нам помогут следующие классы:
- XCTNSPredicateExpectation — ожидание, которое проходит, когда выполняется NSPredicate, самый гибкий вариант. Статья с хорошим объяснением, как использовать NSPredicate
let element = XCUIApplication().buttons["testButton"]
let predicate = NSPredicate(format: "exists == true")
// В этом условии выполнения ожидания мы ждем, что кнопка, иницилизированная выше, существует
let expectation = XCTNSPredicateExpectation(predicate: existsPredicate,
object: element)
- XCTKVOExpectation — ожидание, которое проходит, когда выполняется условие наблюдения за ключевыми значениями(KVO);
let element = XCUIApplication().buttons["testButton"]
// В этом условии выполнения ожидания мы ждем, что кнопка, иницилизированная выше, существует
let expectation = XCTKVOExpectation(keyPath: "exists",
object: element,
expectedValue: true)
XCTNSNotificationExpectation — ожидание, которое проходит при получении уведомления от NSNotificationCenter;
let element = XCUIApplication().buttons["testButton"]
// В этом условии выполнения ожидания мы ждем когда NSNotification отправится из центра уведомлений
let expectation = XCTNSNotificationExpectation(name: NSNotification.Name(rawValue: "exist"), object: element)
XCTDarwinNotificationExpectation — ожидание, которое выполняется при получении ожидаемого уведомления Darwin;
let expectation = XCTDarwinNotificationExpectation(notificationName: "DarwinNotificationName")
Ожидания в XCTestНаписать эффективные ожидания мы можем несколькими способами. Покажу два самых распространенных и эффективных способа:XCTestCase WaitДля использования этого ожидания, вам потребуется наследовать ваш класс с тестами от класса XCTestCase. У этого класса уже есть метод wait(), который можно использовать в своих тестах.
func wait(for expectations: [XCTestExpectation], timeout seconds: TimeInterval)
Метод принимает массив с условиями выполнения ожидания и синхронно ожидает каждое из них в заданном порядке в течение заданного количества времени.Пример:
let element = XCUIApplication().buttons["testButton"]
let existsPredicate = NSPredicate(format: "exists == true")
let expectation = XCTNSPredicateExpectation(predicate: existsPredicate,
object: element)
wait(for: [expectation], timeout: 3)
XCTAssert(element.exists)
XCTWaiter
_ = XCTWaiter.wait(for: [expectation1, expectation2],
timeout: TimeInterval(timeoutValue))
На первый взгляд можно сказать, что этот метод работает также, как и в примере выше. Но в них есть небольшое различие: данный метод возвращает перечисление XCTWaiter.Result. XCTWaiter.Result — это состояния, при которых прекратилось ожидание, разберем их:
- completed — ожидания были успешно выполнены;
- timedOut — истекло время до выполнения ожиданий;
- incorrectOrder — ожидания оправдались в порядке отличном от заданого;
- invertedFulfillment — ожидания выполнились в обратном порядке;
- interrupted — выполнение ожидания было прервано до выполнения условий или до того как истекло заданное время.
Благодаря этому можно более гибко подходить к анализу отчетов после прогона тестов и добавлять необходимы логи, которые помогут в локализации сбоя работы автотестов.Ожидание реализованное с XCTWaiter:
func waitForExpectation(expectation:[XCTestExpectation],
time: TimeInterval) {
let result: XCTWaiter.Result = XCTWaiter().wait(for: [expectation],
timeout: time)
switch result {
case .timedOut:
XCTFail("Condition was not satisfied during \(time) seconds")
case .interrupted:
XCTFail("The waiter was interrupted prior to its expectations being fulfilled or timing out")
case .incorrectOrder:
XCTFail("The waiter’s expectations were not fulfilled in the required order")
case .invertedFulfillment:
XCTFail("An inverted expectation was fulfilled")
default:
break
}
}
Самое важное:
- Есть два вида ожиданий: явные и неявные;
- Используйте неявные ожидания, и тогда ваши тесты будут работать стабильно и быстро;
- Используйте в качестве условия выполнения ожидания XCTNSPredicateExpectation. Это самый гибкий вариант из представленных;
- Используйте XCTWaiter, так как он даёт больше информации при локализации ошибки.
Это последняя статья в цикле статей, но на этом мы не перестаем делиться с вами опытом автоматизации. Напишите в комментариях, на какую тему по iOS автоматизации вам было бы интересно почитать статью.Навигация по статьям:
- Погружение в автотестирование на iOS. Часть 1. Как работать с accessibilityidentifier объектов
- Погружение в автотестирование на iOS. Часть 2. Как взаимодействовать с ui-элементами iOS приложения в тестах
- Погружение в автотестирование на iOS. Часть 3. Жизненый цикл iOS приложения во время прогона тестов
===========
Источник:
habr.com
===========
Похожие новости:
- [Тестирование IT-систем, Тестирование веб-сервисов, Тестирование мобильных приложений, Карьера в IT-индустрии] Курс тестировщика пройден. А дальше что?
- [Разработка под iOS, WebGL, WebAssembly] Есть ли жизнь без WebGL 2.0?
- [Тестирование IT-систем, Java] Автоматизированное тестирование баз данных в Java с помощью JdbcTemplate (перевод)
- [Тестирование IT-систем, IT-инфраструктура, Тестирование веб-сервисов, Тестирование мобильных приложений, Тестирование игр] Самый полный список метрик тестирования на русском языке
- [Разработка под iOS, Разработка мобильных приложений, Swift] Память в Swift от 0 до 1
- [Разработка под iOS, Разработка мобильных приложений, Разработка под Android, Дизайн мобильных приложений, Дизайн] Исправляем Госуслуги малой кровью — добровольный редизайн мобильного приложения
- [Разработка мобильных приложений, Тестирование мобильных приложений, Аналитика мобильных приложений] Приложение Роскомнадзора: кому полезно и насколько хорошо защищает данные
- [Машинное обучение] 17 марта состоится ML meetup Online
- [Разработка под iOS, Разработка мобильных приложений, Разработка под Android] Робопрактика в режиме онлайн для мобильных разработчиков в red_mad_robot
- [Веб-аналитика, Повышение конверсии, Контент-маркетинг] Как в Нью-Йорк таймс тестируют заголовки статей (перевод)
Теги для поиска: #_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-Ноя 11:36
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Привет, Хабр!В UI тестах не все события происходят синхронно друг за другом. Сетевые запросы, анимации, чтение файлов – все это требует времени. Встает вопрос – как заставить тест ждать наступления определенного события?В этой статье мы разберем:
// Ждем 5 секунд
Thread.sleep(forTimeInterval: 5) // Ждём в течении 5 секунд что кнопка есть на экране. Если кнопка отобразится на 2 секунде, ожидание выполнится и мы пойдем дальше
let element = XCUIApplication().buttons["testButton"] let predicate = NSPredicate(format: "exists == true") let expectation = XCTNSPredicateExpectation(predicate: existsPredicate, object: element) wait(for: [expectation], timeout: 5)
let element = XCUIApplication().buttons["testButton"]
let predicate = NSPredicate(format: "exists == true") // В этом условии выполнения ожидания мы ждем, что кнопка, иницилизированная выше, существует let expectation = XCTNSPredicateExpectation(predicate: existsPredicate, object: element)
let element = XCUIApplication().buttons["testButton"]
// В этом условии выполнения ожидания мы ждем, что кнопка, иницилизированная выше, существует let expectation = XCTKVOExpectation(keyPath: "exists", object: element, expectedValue: true) let element = XCUIApplication().buttons["testButton"]
// В этом условии выполнения ожидания мы ждем когда NSNotification отправится из центра уведомлений let expectation = XCTNSNotificationExpectation(name: NSNotification.Name(rawValue: "exist"), object: element) let expectation = XCTDarwinNotificationExpectation(notificationName: "DarwinNotificationName")
func wait(for expectations: [XCTestExpectation], timeout seconds: TimeInterval)
let element = XCUIApplication().buttons["testButton"]
let existsPredicate = NSPredicate(format: "exists == true") let expectation = XCTNSPredicateExpectation(predicate: existsPredicate, object: element) wait(for: [expectation], timeout: 3) XCTAssert(element.exists) _ = XCTWaiter.wait(for: [expectation1, expectation2],
timeout: TimeInterval(timeoutValue))
func waitForExpectation(expectation:[XCTestExpectation],
time: TimeInterval) { let result: XCTWaiter.Result = XCTWaiter().wait(for: [expectation], timeout: time) switch result { case .timedOut: XCTFail("Condition was not satisfied during \(time) seconds") case .interrupted: XCTFail("The waiter was interrupted prior to its expectations being fulfilled or timing out") case .incorrectOrder: XCTFail("The waiter’s expectations were not fulfilled in the required order") case .invertedFulfillment: XCTFail("An inverted expectation was fulfilled") default: break } }
=========== Источник: habr.com =========== Похожие новости:
Блог компании Vivid Money ), #_razrabotka_pod_ios ( Разработка под iOS ), #_swift, #_testirovanie_mobilnyh_prilozhenij ( Тестирование мобильных приложений ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 11:36
Часовой пояс: UTC + 5