[Разработка под iOS, Swift, Тестирование мобильных приложений] Погружение в автотестирование на iOS. Часть 4. Ожидания в XCUITest

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
17-Мар-2021 12:30


Привет, Хабр!В 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)
  • 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 автоматизации вам было бы интересно почитать статью.Навигация по статьям:
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_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