Как ускорить тесты пользовательского интерфейса в Xcode?

Поскольку Xcode 7 имеет хороший API для тестирования пользовательского интерфейса. В основном я доволен этим. Единственная проблема связана со скоростью.

Вначале обычный тестовый пример пользовательского интерфейса (около 15 действий) составлял примерно 25 секунд. Затем я полностью издевался над сетью. Теперь это занимает 20 секунд. Учитывая тот факт, что время берется только анимацией и временем запуска (1 секунда или даже меньше), я полагаю, должен быть способ ускорить его.

Ответ 1

Попробуйте установить это свойство, когда выполняются ваши тесты пользовательского интерфейса:

UIApplication.shared.keyWindow?.layer.speed = 100

Вот как я его установил:

func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    if ProcessInfo.processInfo.arguments.contains("UITests") {
        UIApplication.shared.keyWindow?.layer.speed = 100
    }
}

И в моих тестах пользовательского интерфейса:

class MyAppUITests: XCTestCase {

    // MARK: - SetUp / TearDown

    override func setUp() {
        super.setUp()

        let app = XCUIApplication()
        app.launchArguments = ["UITests"]
        app.launch()
    }
}

Там еще несколько полезных советов в этом сообщении в блоге.

Ответ 2

Другая возможность - отключить анимацию вообще:

[UIView setAnimationsEnabled:NO];

Swift 3:

UIView.setAnimationsEnabled(false)

Ответ 3

Следуя ответу @Mark, версия Swift 3:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    if ProcessInfo.processInfo.arguments.contains("UITests") {
        UIApplication.shared.keyWindow?.layer.speed = 200
    }
}

На файле ui test:

override func setUp() {
    super.setUp()

    // Put setup code here. This method is called before the invocation of each test method in the class.

    let app = XCUIApplication()
    app.launchArguments = ["UITests"]
    app.launch()

Ответ 4

Добавьте его в doneFinishLaunch

[UIApplication sharedApplication].keyWindow.layer.speed = 2;

Значение по умолчанию равно 1, чтобы удвоить скорость до 2.

Ответ 5

Я хотел отключить ВСЕ анимации во время тестирования снимка. Я смог добиться этого, отключив анимации Core Animation и UIView, как показано ниже.

Обратите внимание, потому что мое приложение использовало раскадровки UIApplication.shared.keyWindow при запуске UIApplication.shared.keyWindow нулю, поэтому я обращаюсь к UIWindow, напрямую обращаясь к свойству window.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    if ProcessInfo.processInfo.arguments.contains("SnapshotTests") {
        // Disable Core Animations
        window?.layer.speed = 0
        // Disable UIView animations
        UIView.setAnimationsEnabled(false)
    }
    return true
}

Ответ 6

Запустите их параллельно.

Если у вас есть только 1 сборочный компьютер, вы можете использовать Bluepill: https://github.com/linkedin/bluepill

Если у вас есть несколько компьютеров, вы можете использовать Emcee: https://github.com/avito-tech/Emcee (это также работает для настройки одного компьютера)

У нас есть 50 часов тестов пользовательского интерфейса, и Emcee позволяет нам проводить их за 1 час. Существует несколько приемов, позволяющих ускорить тестирование пользовательского интерфейса, но бессмысленно, если вы не запускаете их параллельно. Например, вы не можете заставить свои 25-секундные тесты выполняться за 0,5 секунды.


Трюки:

  1. Запустите XCUIApplication без переустановки:
XCUIApplication(
    privateWithPath: nil,
    bundleID: "your.bundle.id"
)

Примечание: вы должны запускать приложение с XCUIApplication().launch() по крайней мере один раз за запуск тестового запуска XCUI для установки приложения. Это требует использования частного API.

  1. Вы можете переместить что-то в фоновый поток. Например
let someDataFromApi = getSomeData() // start request asynchronously and immediately return
launchApp() // this can be few seconds
useInTest(someDataFromApi) // access to data will wait request to finish

Вы можете сделать код похожим на то, что нет асинхронных вещей, это будет проще для QA. Мы хотим реализовать это, но мы этого не сделали, так что это просто идея.

  1. Переключитесь на EarlGrey и проведите тесты, которые будут длиться несколько секунд (но они не будут черным ящиком).

  2. Открывайте экраны с помощью глубоких ссылок, если у вас есть глубокие ссылки.

  3. Используйте много частных API и других хаков. Например: вместо того, чтобы переходить через пользовательский интерфейс в приложение "Настройки" и затем сбрасывать настройки конфиденциальности, вы можете вызвать какой-нибудь приватный API.

  4. Никогда не используйте длинные сны. Используйте опрос.