В Райффайзенбанке несколько мобильных приложений, которые должны работать на самых разных девайсах и операционных системах, поэтому мы стараемся автоматизировать рутинные процессы в тестировании. Эта статья показалась нам полезной, и мы решили ее перевести.
foto source: unsplash.com
Если ваше приложение мультиязычное, универсальное и рассчитано на разные девайсы, то на создание скриншотов для каждой конфигурации можно потратить много времени. Представьте, у вас четыре языка, поддержка iPad и iPhone и вам нужно сохранить по 4 экрана, — это 32 скриншота. Процесс необходимо автоматизировать, чтобы не тратить время каждый раз, когда обновляются интерфейсы.
Инструмент XCTestPlan, который появился в XCode 11, позволяет нам создавать несколько конфигураций для тестов. Сейчас конфигурации чаще всего применяются, чтобы определить, как тесты будут запускаться, включая выбор языка для приложения. В этой статье вы узнаете, как можно использовать XCTestPlan, чтобы автоматизировать получение скриншотов.
Давайте настроим отдельный UITests target для автоматизации создания скриншотов, особенно это полезно, если вы не планируете запускать свои основные тесты с этими конфигурациями. Чтобы создать новый таргет, выберите File -> New -> Target и создайте новый UI Testing Bundle. После этого необходимо добавить новый XCTestplan этому таргету. Для этого можно либо использовать меню Product -> Test Plan -> New Test Plan, либо в Scheme Editor выбрать пункт Convert to use Test Plans. Если делать это через меню, то нужно убедиться, что новый таргет есть на вкладке `Test`.
Поскольку мы хотим настроить только параметры языка, то мы можем оставить Shared Settings без изменений и просто добавить по новой конфигурации для каждого языка, который мы поддерживаем. Так выглядят настройки для приложения, поддерживающего английский, немецкий и французский:
Это вся необходимая настройка и запуск XCTestplan.
Ваши UI-тесты, создающие скриншоты, практически ничем не будут отличаться от ваших привычных тестов кроме того, что они будут создавать аттачи. Еще вы можете добавить проверки XCTAssert, чтобы тесты падали, если что-то идет не так.
Другой важный момент: вам может понадобиться waitForExpectations на случай, если ваш UI не будет готов к моменту создания скриншота (появление/скрытие клавиатуры, завершение анимации).
Ниже приведен пример со всеми вспомогательными методами:
Обратите внимание на последнюю функцию. Она принимает название снимка, добавляет идентификатор языка, делает скриншот и возвращает XCTAttachment со значением параметра .keepAlways. Это важно, так как по умолчанию скриншоты, сделанные во время тестов, удаляются, если тесты проходят успешно. Lifiteme важный параметр, поскольку он гарантирует, что скриншот сохранится после того, как тест будет завершен. Во время UI-тестов постоянно снимаются скриншоты. Они очень полезны, когда нужно определить, почему и когда тест упал; но по умолчанию скриншоты будут удалены, если тесты прошли успешно. Таким образом, когда тест testScreenshots() пройдет успешно, у вас останутся только необходимые скриншоты.
Большинство разработчиков предпочитают видеть на своих скриншотах статус-бар с нужным временем, полным сигналом сети и прочими деталями. В Xcode 11 это делается еще проще. Есть утилита xcrun simctl status_bar, которая позволяет задать эти настройки. Это можно добавить как Build Phase:
После этой команды статус-бар будет выглядеть так же, как в маркетинговых материалах Apple. К сожалению, команда не сработает на реальном девайсе, только в симуляторе. Еще надо отметить, что симулятор, который вы используете, должен быть запущен до того, как вы начнете тесты для сбора скриншотов.
Теперь мы можем запускать наши UI-тесты. Когда они пройдут, мы увидим результаты в Report Navigator в Xcode. Тут же будут тесты, содержащие в себе процедуры, сгруппированные по языковым конфигурациям. Процедуры, у которых есть аттачи, помечены скрепкой. Сами изображения можно открыть в QuickLook.
Собирать по отдельности все получившиеся снимки может быть очень трудозатратно, особенно если ваше приложение поддерживает много языков. К сожалению, эти аттачи не оказываются в виде png или jpg среди результатов тестов (еще одно изменение в Xcode 11). Но можно спарсить результаты тестов и найти JSON, который укажет на реальные аттачи и соберет их. Это можно сделать с помощью утилиты xcparse. Она устанавливается с помощью Homebrew и запускается командой:
Дополнительные флаги сгруппируют файлы по устройству, ОС или конфигурации. Названия наших файлов содержат идентификатор языка, поэтому можно просто отсортировать их по имени.
Описанный подход уже позволил нам сэкономить достаточно времени, особенно в ситуациях, когда появлялось требование поддерживать устройство с новым разрешением или значительно обновлялся интерфейс. На WWDC20 хотелось бы увидеть выбор девайсов как часть конфигурации XCTestplan, а пока что приходится выбирать вручную или использовать скрипт, который собирает необходимые для скриншотов в AppStore.
foto source: unsplash.com
Если ваше приложение мультиязычное, универсальное и рассчитано на разные девайсы, то на создание скриншотов для каждой конфигурации можно потратить много времени. Представьте, у вас четыре языка, поддержка iPad и iPhone и вам нужно сохранить по 4 экрана, — это 32 скриншота. Процесс необходимо автоматизировать, чтобы не тратить время каждый раз, когда обновляются интерфейсы.
Инструмент XCTestPlan, который появился в XCode 11, позволяет нам создавать несколько конфигураций для тестов. Сейчас конфигурации чаще всего применяются, чтобы определить, как тесты будут запускаться, включая выбор языка для приложения. В этой статье вы узнаете, как можно использовать XCTestPlan, чтобы автоматизировать получение скриншотов.
Запускаем XCTestplan
Давайте настроим отдельный UITests target для автоматизации создания скриншотов, особенно это полезно, если вы не планируете запускать свои основные тесты с этими конфигурациями. Чтобы создать новый таргет, выберите File -> New -> Target и создайте новый UI Testing Bundle. После этого необходимо добавить новый XCTestplan этому таргету. Для этого можно либо использовать меню Product -> Test Plan -> New Test Plan, либо в Scheme Editor выбрать пункт Convert to use Test Plans. Если делать это через меню, то нужно убедиться, что новый таргет есть на вкладке `Test`.
Поскольку мы хотим настроить только параметры языка, то мы можем оставить Shared Settings без изменений и просто добавить по новой конфигурации для каждого языка, который мы поддерживаем. Так выглядят настройки для приложения, поддерживающего английский, немецкий и французский:
Это вся необходимая настройка и запуск XCTestplan.
Автоматизация создания скриншотов
Ваши UI-тесты, создающие скриншоты, практически ничем не будут отличаться от ваших привычных тестов кроме того, что они будут создавать аттачи. Еще вы можете добавить проверки XCTAssert, чтобы тесты падали, если что-то идет не так.
Другой важный момент: вам может понадобиться waitForExpectations на случай, если ваш UI не будет готов к моменту создания скриншота (появление/скрытие клавиатуры, завершение анимации).
Ниже приведен пример со всеми вспомогательными методами:
func testScreenshots() {
let app = XCUIApplication()
let searchButton = app.buttons["search"]
searchButton.tap()
let keyboard = app.keyboards.firstMatch
waitForExistence(of: keyboard)
app.typeText("Cupertino")
add(takePromoShot(name: "Search"))
let firstResult = app.cells.firstMatch
firstResult.tap()
waitForDisappearance(of: keyboard)
add(takePromoShot(name: "Result"))
}
func waitForExistence(of element: XCUIElement) {
let predicate = NSPredicate(format: "exists == TRUE")
expectation(for: predicate, evaluatedWith: element, handler: nil)
waitForExpectations(timeout: 5.0, handler: nil)
}
func waitForDisappearance(of element: XCUIElement) {
let predicate = NSPredicate(format: "exists == FALSE")
expectation(for: predicate, evaluatedWith: element, handler: nil)
waitForExpectations(timeout: 5.0, handler: nil)
}
func takePromoShot(name: String) -> XCTAttachment {
let lang = Locale.preferredLanguages[0]
let screenshot = XCUIScreen.main.screenshot()
let attachment = XCTAttachment(screenshot: screenshot)
attachment.lifetime = .keepAlways
attachment.name = "\(lang)-\(name)"
return attachment
}
Обратите внимание на последнюю функцию. Она принимает название снимка, добавляет идентификатор языка, делает скриншот и возвращает XCTAttachment со значением параметра .keepAlways. Это важно, так как по умолчанию скриншоты, сделанные во время тестов, удаляются, если тесты проходят успешно. Lifiteme важный параметр, поскольку он гарантирует, что скриншот сохранится после того, как тест будет завершен. Во время UI-тестов постоянно снимаются скриншоты. Они очень полезны, когда нужно определить, почему и когда тест упал; но по умолчанию скриншоты будут удалены, если тесты прошли успешно. Таким образом, когда тест testScreenshots() пройдет успешно, у вас останутся только необходимые скриншоты.
Привычный статус-бар
Большинство разработчиков предпочитают видеть на своих скриншотах статус-бар с нужным временем, полным сигналом сети и прочими деталями. В Xcode 11 это делается еще проще. Есть утилита xcrun simctl status_bar, которая позволяет задать эти настройки. Это можно добавить как Build Phase:
xcrun simctl status_bar booted override --time 9:41 --operatorName ' ' --cellularMode active --cellularBar 4 --wifiBars 3 --batteryState charged
После этой команды статус-бар будет выглядеть так же, как в маркетинговых материалах Apple. К сожалению, команда не сработает на реальном девайсе, только в симуляторе. Еще надо отметить, что симулятор, который вы используете, должен быть запущен до того, как вы начнете тесты для сбора скриншотов.
Сбор получившихся скриншотов
Теперь мы можем запускать наши UI-тесты. Когда они пройдут, мы увидим результаты в Report Navigator в Xcode. Тут же будут тесты, содержащие в себе процедуры, сгруппированные по языковым конфигурациям. Процедуры, у которых есть аттачи, помечены скрепкой. Сами изображения можно открыть в QuickLook.
Собирать по отдельности все получившиеся снимки может быть очень трудозатратно, особенно если ваше приложение поддерживает много языков. К сожалению, эти аттачи не оказываются в виде png или jpg среди результатов тестов (еще одно изменение в Xcode 11). Но можно спарсить результаты тестов и найти JSON, который укажет на реальные аттачи и соберет их. Это можно сделать с помощью утилиты xcparse. Она устанавливается с помощью Homebrew и запускается командой:
xcparse screenshots /path/to/Test.xcresult /path/to/outputDirectory
Дополнительные флаги сгруппируют файлы по устройству, ОС или конфигурации. Названия наших файлов содержат идентификатор языка, поэтому можно просто отсортировать их по имени.
Заключение
Описанный подход уже позволил нам сэкономить достаточно времени, особенно в ситуациях, когда появлялось требование поддерживать устройство с новым разрешением или значительно обновлялся интерфейс. На WWDC20 хотелось бы увидеть выбор девайсов как часть конфигурации XCTestplan, а пока что приходится выбирать вручную или использовать скрипт, который собирает необходимые для скриншотов в AppStore.