Pull to refresh

Автоматизация процесса разработки под Android: начало

Reading time 4 min
Views 25K

Две недели назад закончилась Школа Автоматизации Процессов Разработки (ШАПР) в санкт-петербургском Яндексе.
Забегая вперёд, скажу, что преподавателям удалось главное: за неполных три месяца они «испортили» наше восприятие процесса разработки, как и обещали в начале Школы. Ручное тестирование и сборка начали жутко раздражать, вызывая мысли вроде «а ведь сейчас, вместо выполнения рутинных операций, я бы мог писать красивый код ...».

Подробнее о том, как им это удалось, можно прочитать здесь и ещё немного здесь.

В практической части обучения мы реализовали web-блог, на базе перечисленных по ссылке выше технологий.
Меня, как android-разработчика, заинтересовала возможность применения этих технологий и инструментов для организации Continuous Integration для Android.
Вдохновлённый докладом Алексея Коровянского на MBLTDev, и, особенно, результатами Google Test Automation Conference 2014 касательно тестирования Android-приложений, я реализовал упрощенный аналог нашего учебного проекта под другую платформу, перенеся туда всё что смог и успел. На этом предисловие заканчивается и начинается собственно описание автоматизации.

1. Автоматизированное тестирование


Мы говорим автоматизация, подразумеваем — тесты; говорим тесты, подразумеваем — автоматизация.
Тестирование, зачастую, одна из самых ресурсоёмких частей процесса разработки. Текст на кнопке можно поменять за пару минут (включая время запуска IDE), собрать проект ещё за пару минут — а потом несколько часов проверять, не поехала ли вёрстка во всех местах использования этой кнопки при всех контрольных разрешениях экрана. Если этот процесс не автоматизирован, конечно.

К счастью, в декабре 2014 Google всё-таки порадовал android-разработчиков, включив фреймворк Espresso в Android Support Repository. Ура! Наконец-то у нас есть мощный, достаточно стабильный инструмент написания системных тестов, который поддерживает разработчик операционной системы (помимо всего прочего, это даёт надежду, что тесты не посыпятся с выходом новой версии Android).
Про Espresso на Хабре уже писали, так что я ограничусь замечанием, что в текущей версии он позволяет синхронизировать операции в тестах не только с UI Thread и AsyncTasks, но и с произвольными фоновыми операциями (http-запросами, к примеру). Пример реализации системных и интеграционных тестов можно посмотреть в моём проекте на github, ссылка в конце статьи.

2. Автоматизированная сборка


В наш просвещённый век, наверное, нет необходимости описывать преимущества, которые даёт использование систем сборки.
В ШАПР мы использовали Maven, но под Android Studio с её поддержкой Gradle «из коробки», что-то другое использовать просто неудобно.
Для запуска тестов использовались задачи
  • connectedAndroidTest — из списка типовых gradle tasks
  • spoon — появляется при установке соответствующего плагина. Очень полезная разработка команды Square под руководством небезызвестного Jake Wharton. Позволяет запускать тесты на нескольких подключенных android-устройствах одновременно, делать с них скриншоты, и многое другое

Вот так выглядят результаты тестов в интерпретации Gradle 2.2.1
image

А так результат запуска тестов для трёх устройств (два виртуальных и одно реальное) одновременно покажет Spoon. Детализация по нажатию на конкретный тест присутствует
image

3. Автоматизированный запуск тестов


Если вы каким-то чудом не используете 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-тестов

Результат выглядит следующим образом
image

Вообще запуск тестов на реальных устройствах и виртуальных образах genymotion показал лучшие по быстродействию, стабильности и реалистичности результаты, чем стандартный эмулятор Android от Google, так что от его использования в тестировании я на данный момент отказался.

4. Пару слов про разделение окружений


Речь идёт об использовании разных, к примеру, баз данных для 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

Пользуясь случаем, хочу искренне поблагодарить наших инструкторов в ШАПР и Яндекс в целом.
Вы в очередной раз сделали мир немножко лучше. Спасибо! :-)
Only registered users can participate in poll. Log in, please.
Я android-разработчик и
3.74% использую автотесты 13
9.77% использую систему непрерывной интеграции (например, Jenkins) 34
6.61% использую и автотесты и CI-сервер 23
53.45% не использую средства автоматизации, но хотел бы попробовать 186
26.44% ничего такого не использую, и так всё работает 92
348 users voted. 100 users abstained.
Tags:
Hubs:
+18
Comments 3
Comments Comments 3

Articles