Всем привет!
Меня зовут Борис. Я AQA iOS-engineer в Vivid Money.
Это вступительная статья, в цикле статей по iOS-автоматизации, в которых хочется рассказать о пользе ui-тестов на проекте, их эффективном использовании и написании.
Данная статья будет полезна начинающим iOS-автоматизаторам, либо разработчикам, которые решили изучить XCUITest и покрыть свой проект ui-тестами.
В рамках этой статьи, мы разберем такие этапы:
Что такое ui-тесты и какую пользу они приносят.
Установка и настройка окружения.
Нахождение ui-элементов в проекте и проставление им accessibilityidentifier.
Что такое UI-тесты?
Когда мы слышим слово 'тестирование', мы обычно представляем проверку приложения по тест-кейсам. А что если можно не проходить тест-кейсы на регрессе самим, а доверить это рутинное дело машине?
В этом случае помогают ui-тесты. Они сокращают время проведения регресса и могут предоставлять актуальную информацию о приложении без вашего участия!
Цель этих тестов — проверить, что интерфейс приложения ведет себя в соответсвии с спецификацией: кнопки имеют необходимое состояние, отображается ожидаемый текст и навигация в приложении происходит так, как мы ожидаем.
Код, который вы пишете, имитирует действия пользователя с приложением, заставляя приложение отрабатывать так, как будто вы сами совершаете эти действия на своем телефоне. И в ходе этих действий мы можем проверять интересующие нас условия.
Какая польза от UI-тестов?
Написание кода для автотестов занимает немало времени, а их поддержание в актуальном состоянии и того больше, НО в долгосрочной перспективе это сократит время проверки приложения во время регрессионного тестирования.
Написание UI тестов имеет множество преимуществ, особенно в тех случаях, когда приложение разрастается, и его все сложнее поддерживать.
Какие преимущества есть:
Тесты выполняются быстрее, чем их проходит manual QA;
Тесты можно запускать каждую ночь и получать отчет о качестве приложения к моменту выхода на работу утром;
Тесты не подвержены человеческому фактору и не упустят даже самую малозаметную деталь;
Берегут нервы вашего тестировщика на регрессе — ему не приходится проходить тест-кейсы по 100500 раз;
Сокращают время проведения регрессионного тестирования.
Выглядит все конечно классно, но неужели нет минусов, спросите вы? Они есть и весьма весомые:
Пользовательский интерфейс может меняться, и ваши тесты могут устареть;
Участники команды должны уметь писать ui-тесты;
Тесты требуют обслуживания;
Достаточно хрупкие по сравнению с unit-тестами (если изменится положение кнопки — ui-тест может не пройти);
Также достаточно долго проходят по сравнению с unit-тестами (unit-тесты проходят меньше чем за секунду, ui-тесты будут запускать только приложение секунд 5).
Несмотря на эти недостатки, я считаю, что если у вас крупный проект, ui-тесты имеют право на существование.
Настраиваем среду:
Для того чтобы появилась возможность писать ui-тесты, нам нужно выполнить следующие действия. Если вы создаете новый проект, вам достаточно включить таргет с UI-тестами в момент создания проекта.
Если у вас уже есть проект, то для добавления таргета с ui-тестами вам понадобится:
Нажать на File > New > Target.
Выбрать UI Testing Bundle.
Нажать на Next и ввести название.
Нажать Finish.
Xcode создаст новый таргет с пустым UITest файлом. Он вам понадобится для написания и запуска тестов.
Мы подготовили проект и разобрали, что за зверь такой, эти ui тесты. Теперь мы готовы разобрать пожалуй одну из базовых вещей в автотестах — это Accessibilityidentifier или как говорят в обиходе айдишник.
Что такое Accessibilityidentifier?
Accessibilityidentifier — Это строка идентефецирующая ваш ui-элемент.
Accessibilityidentifier позволяет найти нужный вам ui-элемент при выполнении автотеста.
Взаимодействовать с ui-элементами можно не только по accessibilityidentifier, но также по индексу, координатам и другими способами. Но использование accessibilityidentifier при взаимодействии с ui делает ваши тесты более надежными и спасает вас от ситуации, когда добавили новый элемент на экран, изменили расположение текущих или изменили название элемента — вследствие чего ваши тесты начали падать.
Проставление id Объектам
Рассмотрим несколько способов проставления accessibilityidentifier объектам в зависимости от реализации проекта.
Проект, реализованный через storyboard
Выбрать storyboard.
Развернуть the Utilities.
Выбрать Identity Inspector.
Выбрать ваш объект на storyboard.
Активировать Enabled.
Ввести название identifier (в примере: button).
Проект, реализованный через SwiftUI
Выбрать нужный View.
Добавить метод .accessibility(identifier: "nameOfID") к нужному объекту.
Проект, реализованный через код
Выбрать нужный ViewController.
Присвоить accessibilityidentifier в viewDidLoad к необходимому объекту.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
button.accessibilityIdentifier = "button"
}
}
Нахождение id Объектов
Мы разобрались, как присвоить accessibilityidentifier объектам, теперь рассмотрим несколько способов, как найти нужный id объекта.
Accessibility Inspector
Нативный инструмент Xcode. Он позволяет вам определить, есть ли у нужного объекта id без запуска самого теста.
Для его использования вам необходимо:
Собрать приложение на симуляторе и запустить его.
Нажать Xcode.
Нажать Open Developer Tools.
Нажать Accesibility Inspector.
В Accessibility Inspector выбрать ваш симулятор с запущенным приложением.
Нажать на значок в виде мишени.
Тапнуть на интересующий элемент в приложении.
Дальше отобразится информация о выделенном объекте:
Basic
Label — Текстовое значение, которое находится в выделенном объекте.
Value — Значение, которое находится в выделенном объекте. Например, заполненый текст в TextFields.
Traits — Название объкта (Например: Button, Static Text).
Identifier — Название id выделенного объекта.
Actions:
Здесь отображаются действия, которые возможно выполнить с объектом. Это может быть свайп, нажатие и другие.
Element:
Class — Класс выделенного объекта.
Address — Адрес объекта в памяти.
Controller — View Controller, в котором находится объект.
Hierarchy:
Раздел в котором отображается иерархия объектов на экране. Этот раздел удобен когда не получается выделить этот объект курсором и можно в него провалиться по иерархии чтобы узнать id.
Console (lldb)
Для использования этого способа понадобится поставить брейкпоинт в вашем тестовом сценарии и в момент выполнения, когда брейкпоинт сработает, написать в дебаг консоль:
po XCUIApplication().debugDescription
Где po — print object команда, чтобы вывести информацию об объекте.
XCUIApplication — класс, позволяющий запускать приложение и взаимодействовать с его ui элементами.
debugDescription — свойство, отображающие иерархию элементов на экране.
Attributes: Application, pid: 67835, label: 'UiTestssProjects'
Element subtree:
>Application, 0x6000026290a0, pid: 67835, label: 'UiTestssProjects'
Window (Main), 0x600002629180, {{0.0, 0.0}, {375.0, 667.0}}
Other, 0x600002629260, {{0.0, 0.0}, {375.0, 667.0}}
Other, 0x600002629340, {{0.0, 0.0}, {375.0, 667.0}}
Other, 0x600002629420, {{0.0, 0.0}, {375.0, 667.0}}
Button, 0x600002629500, {{40.0, 156.0}, {46.0, 30.0}}, label: 'Button'
StaticText, 0x6000026295e0, {{40.0, 162.0}, {46.0, 18.0}}, label: 'Button'
StaticText, 0x6000026296c0, {{144.0, 161.0}, {42.0, 21.0}}, label: 'Label'
Button, 0x6000026297a0, {{40.0, 216.0}, {46.0, 30.0}}, identifier: 'ButtonID', label: 'Button'
StaticText, 0x600002629880, {{40.0, 222.0}, {46.0, 18.0}}, label: 'Button'
Switch, 0x600002629960, {{183.0, 245.0}, {51.0, 31.0}}, value: 1
Button, 0x600002629a40, {{40.0, 268.0}, {46.0, 30.0}}, label: 'Button'
StaticText, 0x600002629b20, {{40.0, 274.0}, {46.0, 18.0}}, label: 'Button'
TextField, 0x600002629c00, {{133.0, 374.0}, {97.0, 34.0}}
Window, 0x600002629ce0, {{0.0, 0.0}, {375.0, 667.0}}
Other, 0x600002629dc0, {{0.0, 0.0}, {375.0, 667.0}}
Other, 0x600002629ea0, {{0.0, 0.0}, {375.0, 667.0}}
Path to element:
>Application, 0x6000026290a0, pid: 67835, label: 'UiTestssProjects'
Query chain:
>Find: Target Application 'fox.UiTestssProjects'
Output: {
Application, pid: 67835, label: 'UiTestssProjects'
}
В этой иерархии мы видим, что за элементы есть на экране, их координаты, текст в них, значение, и, самое главное, identifier.
Test Recorder
Test recorder — нативный инструмент от Apple, который пишет тестовые сценарии за вас. Вам лишь нужно запустить его и прокликать необходимые шаги на симуляторе в запущенном приложении.
Чтобы рекордер стал активным вам нужно:
UI test target(ссылка) в вашем проекте;
Тестовый класс с методом, который начинается с test.
Для использования этого способа достаточно в методе вашего теста нажать на record и нажать на нужный вам объект на симуляторе. Если у этого объекта есть id — он отобразится в сгенерированом коде, если нет — можно увидеть, как альтернативным способом обратиться к нужному объекту.
Заключение:
Ui-тесты — это классный инструмент для повышения качества вашего продукта, но он не всегда необходим. Чтобы понять целесообразность его применения в вашем проекте, можно обратиться к статьям, в которых приводятся конкретные моменты, когда нужно или не нужно это делать. Вот пример такой статьи.
В следующей статье, мы расскажем про то, какие бывают ui-элементы в iOS-приложении и как с ними взаимодействовать при написании ui-тестов.
amedvedjev
Занимаюсь тем же, только на Аппиуме. Интересно почитать как в чистом XCUITest.
Хотелось бы дальше продолжения и сравнить:
— как параллелить тесты в XCUITest (1 тест = 1 тел)
— можно ли сохранять видео теста
— как быстро бегут (скажем 100 тестов с 5-10 тел)
Boris_Lys Автор
Как параллелить тесты в XCUITest (1 тест = 1 тел):
— Мы пока гоняем тесты на 1 симуляторе, но в скором времени хотим использовать плагин fastlane-plugin-test_center для fastLane, плюс поресерчим эту тему, может найдем вариант интересней.
Можно ли сохранять видео теста:
— Я не встречал такого, возможно есть такая возможность. Мы используем скриншоты, когда тест не проходит, автоматом делается скриншот и потом в отчете, мы можем посмотреть, что пошло не так.
Как быстро бегут (скажем 100 тестов с 5-10 тел):
— Общее время будет зависеть от самого долгого прогона на одном из симуляторов. Допустим у вас прогон всех тестов занимает 100 минут. Вы делите их на 5 симуляторов. На первом симуляторе это занимает 60 минут, а на остальных проходит за 10 минут. В таком случае общее время прогона будет упираться в самый долгий прогон.
amedvedjev
5 симуляторов на 1 машине? Думаю с трудом. Проще реальные тел. Реальные у нас сейчас 20 тел тянет один макМини с видео :).
ПС ясно что скорость зависит от самого продукта и кол-ва шагов. Я думал у вас уже есть цифры. Хотел сравнить с нашими. Хоть примерно.
Boris_Lys Автор
5 симуляторов возможно на новом mac mini.
С реальными телефона не пробовали, но это интересный опыт, как мне кажется)
Цифр к сожалению нет