Хабр привет!
Меня зовут Борис. Я руководитель группы автоматизации тестирования в Звук.
В этой статье я хочу рассказать про старт приложения с определенного экрана и какие способы реализации данного подхода существуют.
Данная статья будет полезна iOS‑автоматизаторам с опытом, либо разработчикам.
В рамках этой статьи мы разберем:
Зачем стартовать приложение с определенного экрана?
Какие способы реализации существуют?
Реализация с помощью диплинков
Реализация с помощью ArgumentHandler для подмены стартового View
Плюсы и минусы обоих подходов
Зачем стартовать приложение с определенного экрана?
В тест‑кейсах часто встречаются проверки, где нужно дойти до определенного экрана и проверить на нём уникальное состояние элемента, которое зависит от ответа бэкенда, например: На экране плейлистов музыки ещё нет созданных плейлистов или наоборот есть. Достаточно затратно по времени проверять данную логику проходя весь флоу и также это не стабильно т.к. при изменении навигации в приложении придется это переписывать, хотя сам экран и логика на нём не была затронута. В таких случаях отличный выбор поднимать экран и сразу совершать необходимую проверку.
Какие способы реализации существуют?
Принято использовать два подхода:
Реализация с помощью диплинков.
Реализация с помощью ArgumentHandler для подмены стартового View.
Реализация с помощью диплинков
Для данного подхода нужно, чтобы в вашем приложении был реализован механизм обработки диплинков и все необходимые вам для тестов экраны были покрыты диплинками. Если эти условия соблюдены, вы можете использовать следующий код для перехода на нужный экран:
Если у вас Xcode версии < 14.3. Данный подход отрабатывает в среднем 7 секунд.
let safari = XCUIApplication(bundleIdentifier: "com.apple.mobilesafari")
let url = safari.textFields.firstMatch
let alertOpenButton = safari.otherElements["SFDialogView"].buttons.element(boundBy: 1)
safari.activate()
url.waitForExistence(timeout: 2)
url.tap()
url.waitForExistence(timeout: 2)
url.typeText("yourApp://deeplink")
safari.keyboards.buttons["go"].waitForExistence(timeout: 2)
safari.keyboards.buttons["go"].tap()
alertOpenButton.waitForExistence(timeout: 2)
alertOpenButton.tap()
Если у вас Xcode версии > 14.3. Данный подход отрабатывает моментально.
В этой версии Apple добавили метод open()
, который позволяет мгновенно открыть диплинк.
XCUIApplication().launch()
let device = XCUIDevice.shared.system
device.open(URL(string: "yourApp://deeplink")!)
Плюсы | Минусы |
---|---|
Простая реализация и поддержка | Все экраны должны поддерживать диплинки |
Проверка корректности работы диплинков |
Реализация с помощью ArgumentHandler для подмены стартового View
Зачастую реализации в проектах бывают более сложными, поэтому данный пример служит ориентиром.
Реализация данного подхода состоит из 3 этапов:
Открыть ваш таргет с ui-тестами и перейти в нужный вам тест. Придумать название для аргумента или переменной, которая бы ассоцировалась с нужным вам экраном или скрином. Как пример название может дублировать название вашего Page в тестах или название ViewController.
// UIKit & SwiftUI
override func setUp() {
XCUIApplication().launchArguments.append("DetailsScreen")
XCUIApplication().launchEnvironment["Screen"] = "DetailsScreen"
}
Создать ArgumentHandler в основном таргете приложения.
// UIKit
struct ArgumentHandler {
static func handleView() -> UIViewController {
let arguments = ProcessInfo.processInfo.arguments
if arguments.contains("DetailsScreen") {
return DetailViewController()
}
return MainViewController
}
}
// SwiftUi
struct ArgumentHandler: View {
var body: some View {
let arguments = ProcessInfo.processInfo.arguments
if arguments.contains("DetailsScreen"){
DetailView()
} else {
ContentView()
}
}
}
Использовать ArgumentHandler для подмены стартового экрана в жизненном цикле приложения. Важно также использовать макрос #DEBUG , чтобы ваша подмена экрана не попала в релизную сборку
// UIKit
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let window = UIWindow()
#if DEBUG
window.rootViewController = ArgumentHandler.handleView()
#else
window.rootViewController = MainViewController()
#endif
window.makeKeyAndVisible()
self.window = window
return true
}
}
// SwiftUI
@main
struct PublicArtApp: App {
var body: some Scene {
WindowGroup {
#if DEBUG
ArgumentHandler()
#else
ContentView()
#endif
}
}
}
Плюсы | Минусы |
---|---|
Экран поднимается моментально | Для реализации нужна помощь разработчика или хороший уровень погружения в проект и разработку |
Самое важное
Если у вас есть тест‑кейсы, в которых целевая проверка находится на определенном экране, поднимайте этот экран. Не нужно начинать флоу с стартового экрана, так как это удлиняет время прохождения вашего теста и делает его менее стабильным.
Если в вашем приложении основные экраны покрыты диплинками, и разработчики готовы идти вам навстречу, добавляя их для экранов, необходимых для вашего тестирования, воспользуйтесь реализацией с диплинками.
Если у вас в приложении отсутствуют диплинки или они не охватывают основные экраны для тестирования, воспользуйтесь реализацией с использованием ArgumentHandler для подмены стартового View.
Навигация по статьям:
Ускоряем прохождение iOS UI‑тестов. Часть 1. Запускаем тесты без сборки проекта
Ускоряем прохождение iOS UI‑тестов. Часть 2. Распараллеливание тестов
Интересуешься автоматизацией на iOS? Подписывайся на мой телеграмм‑канал, в котором я публикую материалы, которые будут полезны как начинающим, так и опытным iOS‑автоматизаторам.