Погружение в автотестирование на iOS. Часть 5. Взаимодействие с system alerts в ui-тестирование.
Привет, Хабр!
При работе с ui-тестами мы переодически сталкиваемся с системными алертами и нотификациями разного типа, которые нам приходится обрабатывать.
Картиники:
Наиболее расспространненый способ взаимодействия с ними - это кликать на нужные кнопки из кода теста или делать отдельный тест в наборе, который явно запускается первым и проходит все алерты при первом запуске приложения.
let springBoardApp = XCUIApplication( bundleIdentifier: CommonPage.AnotherAppIds.springBoard.rawValue ) let app = XCUIApplication() if springBoardApp.alerts.buttons["Allow"] .waitForExistence(timeout: 1) { springBoardApp.alerts.buttons["Allow"].tap() } else if app.alerts.buttons.element(boundBy: 1) .waitForAppear(timeout: 1) { app.alerts.buttons["Allow"].tap() }
Минусы данного способа - это общая нестабильность прогона всего тестового набора. Зачастую может произойти сбой во время прокликивания алертов, что в последствии приведет к частичному падению следующих тестов в наборе.
Второй способо это использовать системный обработчик addUIInterruptionMonitor.
addUIInterruptionMonitor(withDescription: "Tracking Usage Permission Alert") { (alert) -> Bool in if alert.buttons["Allow"].exists { alert.buttons["Allow"].tap() self.app.activate() return true } return false }
Минусы данного способа - это реализация addUIInterruptionMonitor в setUp() не будет отрабатывать автоматически на всех тестах и его нужно вызывать в начале теста и для каждого аллерта нужен отдельный обработчик. Так же addUIInterruptionMonitor плохо взаимодействует с такими алертами, как запрос трекинга активности пользователя.
Третий способ - это управление добавлением в инициализацию делегатов, отвечающих за алерты и нотификации.
Создадим перепенную, которую передается через launcharguments и реализуем обработчики в AppDelegate.
func launch(arguments: [String] = ["UI-TestingNotifications"]) { if state != .notRunning { terminate() launchArguments = [] } launchArguments = arguments launch() _ = wait(for: .runningForeground, timeout: 10) } // In class AppDelegate private lazy var appDelegates: [UIApplicationDelegate] = { if !ProcessInfo.processInfo .arguments.contains("UI-TestingNotifications") { appDelegates.append(pushNotificationsAppDelegate) appDelegates.append(appsFlyerAppDelegate) } }
Таким способом мы сможем явно отключить все виды алертов и нотификаций в тестах и включать их только в нужных тестах, где они являются частью сценария.