Представим ситуацию: вы разрабатываете экран, до которого в приложении очень сложно добраться. Например, надо авторизоваться, положить товар в корзину, оформить заказ, оплатить его… Таких экранов много, особенно на крупных проектах, а время регулярно тратят все участники команды: при разработке, на code review и тестировании. Это особенно ощутимо на крупных проектах, когда таких труднодоступных экранов много.
Если эта ситуация вам знакома — то вы зашли по адресу! Меня зовут Александр Чаусов, и в статье я расскажу, как мы в Surf увеличили скорость тестирования UI.
Эта длинная история началась в 2018 году. Мы работали над крупным банковским проектом, и команда постоянно расширялась: приходили новые разработчики, часто со стороны. Часть времени они тратили не на решение непосредственных задач, а на поиск нужных UI-компонентов в коде.
Мы поняли, что разработчикам проще вливаться в проект, если все переиспользуемые компоненты будут собраны в одном месте, во вспомогательном приложении. Тогда не надо объяснять, где и какие компоненты реализованы: они будут визуально представлены в рамках одного приложения — вместе с названиями, по которым их проще найти непосредственно в проекте. Время на разработку сократится.
Так в команде заговорили о решении, которое позволит объединить в рамках одного вспомогательного приложения все переиспользуемые UI-компоненты. Беглый обзор существующих вариантов выявил вполне подходящую библиотеку — Playbook-ios. Но она имеет ряд недостатков:
Нельзя кастомизировать «на лету», если необходимо посмотреть различные варианты отображения одного компонента.
PlaybookUI работает только на iOS 13.0+. На некоторых наших проектах ещё поддерживаются более ранние версии.
Если бы захотели изменять библиотеку под себя, необходимо было бы детально её изучать, что повлекло бы за собой большие траты времени.
Какой программист не хотел бы написать свой велосипед? Точно не я! «В топку сторонние фреймворки, делаем свой велосипед!» — именно с такой мыслью появилась первая версия решения.
MVP версия: экран с UI-компонентами
На первом этапе реализовали прототип, содержащий задуманную фичу, — экран со списком всех переиспользуемых компонентов.
Все компоненты разделены на группы.
Можно посмотреть компоненты всех групп на одном экране, или все компоненты в рамках конкретной группы.
Есть поиск по названию.
Можно открыть экран детального отображения компонента и посмотреть его поближе.
Если вариантов конфигурации несколько, можно менять конфиг на лету и в реальном времени наблюдать варианты отображения одного и того же компонента.
Казалось, что изначальная цель достигнута. Но в процессе реализации приходили новые идеи: какие проблемы можно решить, расширив функциональность приложения. Так появились два новых таба.
Жизнь после MVP: от компонентов к экранам
Первый таб — UIKit — позволяет наверстать неограниченное количество табличных экранов и разместить в них любой контент.
Здесь можно зафиксировать UIKit приложения: отобразить, к примеру, все используемые цвета, шрифты, кнопки или поля ввода. Новый разработчик, который только что пришёл на проект, сможет легко сопоставить название кнопки с визуальным представлением.
Второй таб — Flows — позволяет создать точки входа на любой экран приложения.
Эта механика решает несколько проблем:
Сокращает время на разработку фичи: не надо собирать реальное приложение и переходить к нужному экрану. Особенно это приятно, если путь до экрана слишком долгий или есть ряд хитрых условий. Например, чтобы добраться до экрана успешного оформления кредитной заявки надо заполнить множество форм на большом количестве экранов. Другой пример: когда пользователь авторизован, у него есть один неоценённый заказ, при этом он находится на главной более 5 секунд, тогда он должен увидеть экран с предложением оценки заказа.
Можно создать собственные плейграунды для экспериментов, а не делать на боевом проекте тестовый экран-заглушку.
Нет необходимости интегрировать экран или UI-компонент сразу в реальное приложение: экран можно запустить из вспомогательного приложения, а компонент сверстать в плейграунде.
Можно структурировать точки входа и объединять их по смыслу благодаря возможности создать вложенную структуру внутри таба.
Чтобы вспомогательное приложение было максимально похоже на реальное, добавили кастомизацию цветов, строк и поддержку тёмной темы. Цветовую палитру или текст на любой кнопке можно изменить.
Результаты интеграции в проект
Маленький инструмент для отображения в единой базе всех переиспользуемых компонентов вырос до полноценного помощника при разработке.
Стало возможно:
быстро найти название компонента,
поэкспериментировать с новым компонентом,
ускорить и облегчить ввод новых разработчиков в проект,
открыть труднодоступный экран,
показать решение дизайнеру до интеграции в реальный проект.
Самой востребованной оказалась возможность открыть любой экран приложения — в том числе и встроенного плейграунда. Теперь можно реализовать фичу до реальной интеграции в проект. Это сохраняет драгоценное время, которое раньше тратилось на перемещение между экранами. На примере гифки из начала статьи: на каждое открытие экрана экономим порядка 7 секунд (практически в 4 раза быстрее!). И такие кейсы в процессе разработки встречаются постоянно.
Стоит помнить, что развёртывание подобного решения на проекте, а также его поддержка занимает некоторое время. Но цифры небольшие: к примеру, на создание стартовой точки для входа на экран уйдёт порядка 2–3 минут. На крупных проектах такие затраты быстро окупаются.
Познакомиться с полученным решением, прочесть документацию и посмотреть Example-проект можно в репозитории на GitHub.
Поделитесь в комментариях своими проверенными способами решения проблем, которые мы затронули сегодня в статье: как разбираетесь с большим количеством переиспользуемых UI-компонентов на проекте и как организуете быстрый доступ к труднодоступным экранам?
x0rHamster
Я правильно понимаю, что вы используете Flows только для ручных проверок во время активной разработки, но НЕ в основном наборе авто- и ручных тестов (необходимых для принятия решения, можно ли релизить приложение или нет, включая юзабилити-тесты вроде "не перекрывают ли компоненты друг друга")? Или, может быть, вы смогли успешно применить подход а-ля фрактального тестирования?
Chausov_surf Автор
Добрый день! Так точно, все правильно поняли, пока только во время активной разработки используется. Но, в целом, ничего не мешает попробовать внедрить решение на этап тестирования, только тут надо будет обдумать и посоветоваться с QA-командой. Опыт написания автотестов у нас имеется, но пишутся они все же на реальное приложение - помимо проверки логики модуля можно попутно проверить и его интеграцию. Если говорить о ручном тестировании и проведении смоука - тут опять же важно понять, не отвалилась ли интеграция той или иной проверяемой фичи.
Возможное применение, которое я вижу - проведение тестов большой фичи со сложной логикой, которая, к тому же, располагается в труднодоступном месте, в таком вспомогательном приложении во время ручных/автотестов (чтоб время на перемещение между экранами не терять) + отдельное проведение интеграционных тестов на реальном приложении.