Автоматизация процесса разработки под Android: начало
Две недели назад закончилась Школа Автоматизации Процессов Разработки (ШАПР) в санкт-петербургском Яндексе.Забегая вперёд, скажу, что преподавателям удалось главное: за неполных три месяца они «испортили» наше восприятие процесса разработки, как и обещали в начале Школы. Ручное тестирование и сборка начали жутко раздражать, вызывая мысли вроде «а ведь сейчас, вместо выполнения рутинных операций, я бы мог писать красивый код …».Подробнее о том, как им это удалось, можно прочитать здесь и ещё немного здесь.
В практической части обучения мы реализовали web-блог, на базе перечисленных по ссылке выше технологий.Меня, как android-разработчика, заинтересовала возможность применения этих технологий и инструментов для организации Continuous Integration для Android.Вдохновлённый докладом Алексея Коровянского на MBLTDev, и, особенно, результатами Google Test Automation Conference 2014 касательно тестирования Android-приложений, я реализовал упрощенный аналог нашего учебного проекта под другую платформу, перенеся туда всё что смог и успел. На этом предисловие заканчивается и начинается собственно описание автоматизации.
Мы говорим автоматизация, подразумеваем — тесты; говорим тесты, подразумеваем — автоматизация.Тестирование, зачастую, одна из самых ресурсоёмких частей процесса разработки. Текст на кнопке можно поменять за пару минут (включая время запуска IDE), собрать проект ещё за пару минут —, а потом несколько часов проверять, не поехала ли вёрстка во всех местах использования этой кнопки при всех контрольных разрешениях экрана. Если этот процесс не автоматизирован, конечно.К счастью, в декабре 2014 Google всё-таки порадовал android-разработчиков, включив фреймворк Espresso в Android Support Repository. Ура! Наконец-то у нас есть мощный, достаточно стабильный инструмент написания системных тестов, который поддерживает разработчик операционной системы (помимо всего прочего, это даёт надежду, что тесты не посыпятся с выходом новой версии Android).Про Espresso на Хабре уже писали, так что я ограничусь замечанием, что в текущей версии он позволяет синхронизировать операции в тестах не только с UI Thread и AsyncTasks, но и с произвольными фоновыми операциями (http-запросами, к примеру). Пример реализации системных и интеграционных тестов можно посмотреть в моём проекте на github, ссылка в конце статьи.
В наш просвещённый век, наверное, нет необходимости описывать преимущества, которые даёт использование систем сборки.В ШАПР мы использовали Maven, но под Android Studio с её поддержкой Gradle «из коробки», что-то другое использовать просто неудобно.Для запуска тестов использовались задачиconnectedAndroidTest — из списка типовых gradle tasks spoon — появляется при установке соответствующего плагина. Очень полезная разработка команды Square под руководством небезызвестного Jake Wharton. Позволяет запускать тесты на нескольких подключенных android-устройствах одновременно, делать с них скриншоты, и многое другое Вот так выглядят результаты тестов в интерпретации Gradle 2.2.1 А так результат запуска тестов для трёх устройств (два виртуальных и одно реальное) одновременно покажет Spoon. Детализация по нажатию на конкретный тест присутствует Если вы каким-то чудом не используете Maven или Gradle, то дальше можете не читать — ни один сервер непрерывной интеграции с вашим проектом дружить не будет.А если используете, то после нескольких запусков нескольких десятков/сотен тестов к проекту у вас возникает большое желание, чтобы это всё происходило самостоятельно, и, желательно, как можно дальше от вашего процессора :-). Здесь нам на помощь приходит Jenkins (TeamCity, Atlassian Bamboo, нужное подчеркнуть). Я использовал Jenkins, которому нас и учили в ШАПР. Про Jenkins и даже непосредственно его отношения с Android-приложениями на Хабре написано тоже немало.В нашем случае, помимо плагинов «по умолчанию», использовалисьGitHub plugin, GIT plugin, GitHub API Plugin — для получения кода и перехвата событий из github Gradle plugin — для запуска gradle tasks Android Emulator Plugin — для запуска приложения на эмуляторе (потом отказался от этой идеи в пользу spoon) HTML Publisher plugin — для публикации описания результатов выполнения тестов произвольного формата на странице задачи JUnit Plugin — для публикации результатов выполнения unit-тестов Результат выглядит следующим образом Вообще запуск тестов на реальных устройствах и виртуальных образах genymotion показал лучшие по быстродействию, стабильности и реалистичности результаты, чем стандартный эмулятор Android от Google, так что от его использования в тестировании я на данный момент отказался. Речь идёт об использовании разных, к примеру, баз данных для testing и production. Для этого в код необходимо транслировать различные настройки. В модельном проекте это реализовано с помощью gradle build flavors, переменные вынесены в отдельный файл с константами, который плагин подставляет в нужную сборку.Итак, как выглядит частично автоматизированный процесс разработки модельного android-приложения на данный момент:1. Написанный код уходит на github.2. Jenkins ловит hook с github и запускает сборку на всех android-устройствах, которые запущены/подключены к серверу/ноду3. По результатам сборки Jenkins отписывается на github/посылает письмо разработчику/зажигает красную или зелёную лампочку над дверью (нужное подчеркнуть)4. В случае успешной сборки установочный файл заливается на тестовые устройства, а тестировщикам-ручникам уходит оповещение, что можно приступать к работе (если это необходимо)5. Возможно даже автоматически опубликовать собранный проект в GooglePlay с помощью Google Play Android Publisher Plugin
TODO: к сожалению ещё не успел поднять SonarQube, хотя в ШАПР мы успели наглядно оценить полезность и важность инструментов анализа кода. Да, и code coverage в тестовом проекте пока не считается. Не успел использовать механизм dependency injection, который очень удобен для написания хорошо тестируемого кода — под Android для этого есть замечательная библиотека Dagger. В общем, есть ещё чем заняться.
Обещанная ссылка на модельный проект (блог с возможностью добавления/удаления постов/комментариев) и дюжину тестов к нему. Не судите код слишком строго, ведь чтобы его имело смысл тестировать, он должен иногда ломаться, верно? ;-)
В проекте использовались библиотеки:
robospice retrofit и okhttp androidannotations cupboard ну и, конечно, espresso Пользуясь случаем, хочу искренне поблагодарить наших инструкторов в ШАПР и Яндекс в целом.Вы в очередной раз сделали мир немножко лучше. Спасибо! :-)
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.