После реализации пары проектов под Android, стало понятно, что, несмотря на их небольшие размеры и кажущуюся простоту, без автоматизированных сборок и тестирования не обойтись. Родилось желание получить следующие возможности:
- unit тестирование,
- интеграционное тестирование,
- тестирование интерфейса,
- тестирование этих типов тестов на различных версиях Android и конфигурациях девайсов,
- рассылка по email в случае сломанного билда;
- таже не помешает автоматическая сборка релизов.
Почти сразу же попался сайт testdroid.com/, которые предлагает почти всё то же, и даже больше (тестирование на реальных девайсах), но, естественно, за денюжку.
В связи с этим после двухнедельных изысканий выбор был остановлен на связке на Jenkins + билд-скрипты на Ant (под Windows).
Итак, как же всё это поднять?!
Предварительные условия:
- Пусть у нас есть уже созданный, каким-либо образом, проект MyProject. И к нему проект для тестирование MyProjectTest (в тестовом проекте есть хоть один тест). И пусть лежат папки с проектами в директории d:projectsMyProjecttrunk. Исходники проекта у меня хранятся под SVN.
- Данный мануал написан при использовании Android SDK версии 16 (http://developer.android.com/sdk/index.html). Если у вас другая версия, возможно что-то придётся сделать по-другому.
Шаг 1. Установка переменных окружения (необязательный, но так проще).
Создаём в окружении системы (System variables) переменную ANDROID_HOME и указываем в её значеии путь до папки Android SDK. У меня это путь D:androidandroid-sdk-windows.
Также добавляем в переменную Path значнеие ;%ANDROID_HOME%platform-tools.
Шаг 2. Установка Ant
Скачиваем zip-архив с http://ant.apache.org/bindownload.cgi и распаковываем в какую-нибудь папку (например d:serverandroidant). Папку antbin также необходимо добавить в системную переменную окружения Path.
Шаг 3. Подготовка build-скрипта для ant.
Google сделала в Android SDK возможность генерировать ant-скрипты для сборки проектов, для этого в папке trunk проекта нужно выполнить команды:
- Для создния build-скрипта для основного проекта:
- android update project -p MyProject
- Для создания build-скрипта для тестового проекта:
- android update test-project -m ..MyProject -p MyProjectTest
Варианты для Android SDK < 14 версии можно посмотреть здесь.
Шаг 4. Проверим сборку проекта (опять необязательный).
- Зайдите в папку trunkMyProject и выполните команду:
- ant clean debug
в конце выполнения должно быть написано что-ть вроде
- BUILD SUCCESSFUL
- Total time: 5 seconds
Это значит, что проект удалось успешно собрать.
- Запустите эмулятор Android и в папке trunkMyProjectTest выполните
- ant all clean emma debug install test
Билд будет идти несколько дольше, в моём случае это было 35 секнунд. В процессе соберутся debug сборки MyProjeсt и MyProjectTest, установятся на запущенный эмулятор и произведётся прогон тестов.
Шаг 5. Установка Jenkins.
Заходим на http://jenkins-ci.org/, там справа есть ссылки на дистрибутивы, скачиваем и устанавливаем. По-умолчанию он устанавливается и предоставляет веб-интерфейс по адресу http://127.0.0.1:8080/.
Тут есть небольшая проблема. По умолчанию сервис Jenkins стартует из-под пользовательского аккаунта System, что ведёт к невозможности для плагина, рулящего эмуляторами, создавать AVD в домашней папке аккаунта. Пользователя нужно поменять либо на ваш аккаунт, либо создать специальный аккаунт для Jenkins’а.
Если кто вдруг не знает, для этого нужно зайти в Computer Management (самы простой способ: Start > Computer (правой кнопкой) > Manage (Управление)), там выбираем Services and Applications > Services, находим сервис Jenkins > Properties > закладка LogOn. После смены аккаунта сервис необходимо перезапустить.
Шаг 6. Настройка Jenkins.
Итак, захоидм по адресу http://127.0.0.1:8080/, выбираем Manage Jenkins далее выбираем Manage Plugins. Перейдите на вкладку Available Plugins. Если тут пусто, подождите некоторое время, Jenkins их просто ещё не подгрузил.
Нам понадобятся следующие:
- Jenkins Emma plugin
- Android Emulator Plugin
- Hudson Port Allocator Plug-in
- ant
Возможно некоторые из них у вас уже буду установлены изначально.
В моём случае потрбовалось ещё установить Subversion Plugin, поскольку у меня проект лежал в SVN. Если ваш проект находится под другой SCM, не забудьте установить для неё плагин.
Теперь, нажимаем кнопку «Install without restart” внизу, в процессе можно поставить галку »Restart Jenkins when installation is complete and no jobs are running” чтобы Jenkins перезапустился автоматом и плагины заработали.
Далее идём в Manage Jenkins > Configure System. Здесь
- в секции Android нужно прописать Android SDK root (как уже писалось выше, в нашем случае это D:androidandroid-sdk-windows)
- Для рассылки email при поломке билда так же стоит заполнить секцию E-mail Notification.
Теперь создадим задание для Jenkins. На главной странице нажимаем New Job, вводим название, тип задания выбираем Build a free-style software project.
Тут необходимо заполнить следующие секции:
- Source Code Management — выбираем тип вашей системы контроля версий и вводим необходимые параметры. Внимание! Необходимо, чтобы из репозитария вытягивалась только папка trunk, иначе вам нужно будет подправлять все пути, которые будут дальше в настройках задания для Jenkins.
- Build Triggers — выбираем Poll SCM и прописываем туда * * * * *. Это будет означать, что Jenkns будет проверять репозитарий раз в минуту и, если там будут новые коммиты, запускать билд. Для сборки раз в 5 минут можно указать */5 * * * *.
- Build Environment — Тут лучше поставить галочку Assign unique TCP ports to avoid collisions.
- Run an Android emulator during build. Заполняем параметры эмулатора, например
- Android OS Version: 2.1 (Убедитесь, что данная версия скачана у вас в SDK)
- Screen density: 240
- Screen resolution: WVGA
- Device locale: en_US
- SD card size: 16M
- Раздел Build, добавляем Invoke Ant, в здесь
- Target: all clean emma debug install test
- Build File: QuickMeetingTestbuild.xml
- Properties: sdk.dir=D:\android\android-sdk-windows (именно так, с двойными слешами)
- Раздел Post-build Actions
- Archive the artifacts: **/*test-TEST.xml
- Publish JUnit test result report: **/*test-TEST.xml
- Record Emma coverage report: **/coverage.xml
- Record fingerprints of files to track usage: **/*test-TEST.xml
- E-mail Notification — настроить по своему вкусу.
Собственно, с настройкой Jenkins почти закончили, но не спешите, пока ещё не всё готово.
Есть две проблемы.
Проблема 1.
Стандартный InstrumentationTestRunner не генерирует xml с результатами прохождения тестов. Поэтому MyProjectTest надо чуть подкрутить.
- Идём на http://code.google.com/p/the-missing-android-xml-junit-test-runner/ Качаем оттуда polidea_test_runner_1.1.jar, кладём в trunkMyProjectTestlibs и добавляем Java Build PathLibraries в свойствах проекта.
- В AndroidManifest.xml меняем <instrumetation>, чтобы оно выглядело так:
- <instrumentation
- android:name="pl.polidea.instrumentation.PolideaInstrumentationTestRunner"
- android:targetPackage="com.example.MyProject" />
- test.runner=pl.polidea.instrumentation.PolideaInstrumentationTestRunner
- <!-- version-tag: 1 -->
меняем 1 на custom (нужно, чтобы ваши изменения в этом вайле не перетёрлись при следующем выполнении android update).
Проблема 2.
Xml-файл с результатами прогона тестов и файл с результатами проверки покрытия генерируется на устройстве. Их необходимо оттуда достать, чтобы Jenkins их подхватил.
Основной скрипт ant, который собственно и собирает проект находится в ${sdk.dir}/tools/ant/build.xml и импортируется в билд-скрипт проекта строчкой
- <import file="${sdk.dir}/tools/ant/build.xml" />
- Идём в ${sdk.dir}/tools/ant/build.xml, берём оттуда всю секцию <target name=«test» ../> и вставляем в наш build.xml в тестовом проекте до вышеуказанного импорта основного скрпта.
Это переопределит вызов цели test и, когда мы модифицируем её, будут работать наши изменения. - В <target name=«test» ../> в нашем build.xml ищем
- <html outfile="coverage/coverage.html" />
и рядом добавляем
- <xml outfile="coverage/coverage.xml" />
Шаг 7. Добавление тестов UI.
Для этого есть удобный инструиент Robotium. Взять можно здесь code.google.com/p/robotium/.
Настройка:
- Скачиваем robotium-solo-3.1.jar (на данный момент это последняя версия), кладём в trunkMyProjectTestlibs.
- Добавляем в свойствах проекта в Java Build PathLibraries
- Создаём тестовый класс и наследуем его от ActivityInstrumentationTestCase2<MyActivity>, в конструкторе должен быть вызов вида
- super("com.example.myproject", MyActivity.class);
где «com.example.myproject» — пакет тестируемого проекта, MyActivity — тестируемая Activity.
- Добавляем в класс строчки
- private Solo solo;
- @Override
- public void setUp() throws Exception {
- solo = new Solo(getInstrumentation(), getActivity());
- }
- @Override
- public void tearDown() throws Exception {
- solo.finishOpenedActivities();
- }
и далее можно писать тесты вида
- public void testPreferenceIsSaved() throws Exception {
- solo.sendKey(Solo.MENU);
- solo.clickOnText("More");
- solo.clickOnText("Preferences");
- solo.clickOnText("Edit File Extensions");
- Assert.assertTrue(solo.searchText("rtf"));
- solo.clickOnText("txt");
- solo.clearEditText(2);
- solo.enterText(2, "robotium");
- solo.clickOnButton("Save");
- solo.goBack();
- solo.clickOnText("Edit File Extensions");
- Assert.assertTrue(solo.searchText("application/robotium"));
- }
Подробности можно почитать тут code.google.com/p/robotium/w/list.
Шаг 8. Тестирование на нескольких эмуляторах.
- При создании задания для Jenkins можно выбрать тип задания Build multi-configuration project.
- В разделе Configuration Matrix создаём оси для каждого изменяющегося параметра, например, разрешение и версия андроид и подставляем в настройки Run emulator with properties в виде ${resolution}. Посмотрите картинки по вышеуказанной ссылке, всё станет понятно.
- Остальные параметы указываем как в обычном задании.
Подробности тут.
Шаг 9. Подготовка релизной сборки.
Релизную сборку собрать попроще, чем запустить тесты.
- Создаём в Jenkins задачу MyProjectRelease (тип Build a free-style software project).
- Как в шаге 6, указываем откуда тянуть исходники.
- Создаём Invoke Ant Build Step с параметарми:
- Targets:
- release
- Build File:
- MyProjectbuild.xml
- Properties:
- sdk.dir=D:\android\android-sdk-windows
- key.store=..\myproject.keystore (относительный путь к файлу-хранилищу ключа, сам ключ я положил в trunk)
- key.alias=<alias>
- key.store.password=<pass>
- key.alias.password=<pass>
- Можно ещё настроить Archive the artifacts с Files to archive = ***-release.apk (если вы хотите бережно хранить все релизы и иметь возможность их скачивать через веб-интерфейс Jenkins).
- Для обфускации релиза при помощи ProGuard потребуется всего лишь добавить в project.properties (или в properties шага InvokeAnt задания в Jenkins) строчку proguard.config=proguard.cfg, где
- proguard.config — имя переменной, в которой должно находиться имя файла с настройками для ProGuard,
- а файл proguard.cfg автоматически создаётся Eclipse при создании проекта.
Спасибо за внимание, надеюсь этот пост поможет сделать ваши программы чуточку лучше.
Автор: bivy