Разработка под Android / [Из песочницы] Continuous Integration для Android

в 16:42, , рубрики: android, Jenkins, метки: ,

После реализации пары проектов под Android, стало понятно, что, несмотря на их небольшие размеры и кажущуюся простоту, без автоматизированных сборок и тестирования не обойтись. Родилось желание получить следующие возможности:

  • unit тестирование,
  • интеграционное тестирование,
  • тестирование интерфейса,
  • тестирование этих типов тестов на различных версиях Android и конфигурациях девайсов,
  • рассылка по email в случае сломанного билда;
  • таже не помешает автоматическая сборка релизов.


Почти сразу же попался сайт testdroid.com/, которые предлагает почти всё то же, и даже больше (тестирование на реальных девайсах), но, естественно, за денюжку.
В связи с этим после двухнедельных изысканий выбор был остановлен на связке на Jenkins + билд-скрипты на Ant (под Windows).

Итак, как же всё это поднять?!

Предварительные условия:

  1. Пусть у нас есть уже созданный, каким-либо образом, проект MyProject. И к нему проект для тестирование MyProjectTest (в тестовом проекте есть хоть один тест). И пусть лежат папки с проектами в директории d:projectsMyProjecttrunk. Исходники проекта у меня хранятся под SVN.
  2. Данный мануал написан при использовании 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 проекта нужно выполнить команды:

  1. Для создния build-скрипта для основного проекта:

    1. android update project -p MyProject

  2. Для создания build-скрипта для тестового проекта:

    1. android update test-project -m ..MyProject -p MyProjectTest

Варианты для Android SDK < 14 версии можно посмотреть здесь.

Шаг 4. Проверим сборку проекта (опять необязательный).

  1. Зайдите в папку trunkMyProject и выполните команду:

    1. ant clean debug

    в конце выполнения должно быть написано что-ть вроде

    1. BUILD SUCCESSFUL
    2. Total time: 5 seconds

    Это значит, что проект удалось успешно собрать.

  2. Запустите эмулятор Android и в папке trunkMyProjectTest выполните

    1. 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. Здесь

  1. в секции Android нужно прописать Android SDK root (как уже писалось выше, в нашем случае это D:androidandroid-sdk-windows)
  2. Для рассылки email при поломке билда так же стоит заполнить секцию E-mail Notification.

Теперь создадим задание для Jenkins. На главной странице нажимаем New Job, вводим название, тип задания выбираем Build a free-style software project.

Тут необходимо заполнить следующие секции:

  1. Source Code Management — выбираем тип вашей системы контроля версий и вводим необходимые параметры. Внимание! Необходимо, чтобы из репозитария вытягивалась только папка trunk, иначе вам нужно будет подправлять все пути, которые будут дальше в настройках задания для Jenkins.
  2. Build Triggers — выбираем Poll SCM и прописываем туда * * * * *. Это будет означать, что Jenkns будет проверять репозитарий раз в минуту и, если там будут новые коммиты, запускать билд. Для сборки раз в 5 минут можно указать */5 * * * *.
  3. Build Environment — Тут лучше поставить галочку Assign unique TCP ports to avoid collisions.
  4. 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
  5. Раздел Build, добавляем Invoke Ant, в здесь
    • Target: all clean emma debug install test
    • Build File: QuickMeetingTestbuild.xml
    • Properties: sdk.dir=D:\android\android-sdk-windows (именно так, с двойными слешами)

  6. Раздел 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

  7. E-mail Notification — настроить по своему вкусу.

Собственно, с настройкой Jenkins почти закончили, но не спешите, пока ещё не всё готово.

Есть две проблемы.

Проблема 1.

Стандартный InstrumentationTestRunner не генерирует xml с результатами прохождения тестов. Поэтому MyProjectTest надо чуть подкрутить.

  1. Идём на http://code.google.com/p/the-missing-android-xml-junit-test-runner/ Качаем оттуда polidea_test_runner_1.1.jar, кладём в trunkMyProjectTestlibs и добавляем Java Build PathLibraries в свойствах проекта.
  2. В AndroidManifest.xml меняем <instrumetation>, чтобы оно выглядело так:

    1.  <instrumentation

  3.        android:name="pl.polidea.instrumentation.PolideaInstrumentationTestRunner"
  4.        android:targetPackage="com.example.MyProject" />

  • В файле project.properties добавляем строчку

    1. test.runner=pl.polidea.instrumentation.PolideaInstrumentationTestRunner

  • И в строке

    1. <!-- version-tag: 1 -->

    меняем 1 на custom (нужно, чтобы ваши изменения в этом вайле не перетёрлись при следующем выполнении android update).

  • Проблема 2.

    Xml-файл с результатами прогона тестов и файл с результатами проверки покрытия генерируется на устройстве. Их необходимо оттуда достать, чтобы Jenkins их подхватил.
    Основной скрипт ant, который собственно и собирает проект находится в ${sdk.dir}/tools/ant/build.xml и импортируется в билд-скрипт проекта строчкой

    1. <import file="${sdk.dir}/tools/ant/build.xml" />

    1. Идём в ${sdk.dir}/tools/ant/build.xml, берём оттуда всю секцию <target name=«test» ../> и вставляем в наш build.xml в тестовом проекте до вышеуказанного импорта основного скрпта.
      Это переопределит вызов цели test и, когда мы модифицируем её, будут работать наши изменения.
    2. В <target name=«test» ../> в нашем build.xml ищем

      1. <html outfile="coverage/coverage.html" />

    и рядом добавляем

    1. <xml outfile="coverage/coverage.xml" />

  • А в конце, перед 
  • Шаг 7. Добавление тестов UI.

    Для этого есть удобный инструиент Robotium. Взять можно здесь code.google.com/p/robotium/.
    Настройка:

    1. Скачиваем robotium-solo-3.1.jar (на данный момент это последняя версия), кладём в trunkMyProjectTestlibs.
    2. Добавляем в свойствах проекта в Java Build PathLibraries
    3. Создаём тестовый класс и наследуем его от ActivityInstrumentationTestCase2<MyActivity&gt, в конструкторе должен быть вызов вида

      1. super("com.example.myproject", MyActivity.class);

      где «com.example.myproject» — пакет тестируемого проекта, MyActivity — тестируемая Activity.

    4. Добавляем в класс строчки

      1. private Solo solo;
      2.  
      3.         @Override
      4.         public void setUp() throws Exception {
      5.                 solo = new Solo(getInstrumentation(), getActivity());
      6.         }
      7.        
      8.         @Override
      9.         public void tearDown() throws Exception {
      10.                 solo.finishOpenedActivities();
      11.         }

    и далее можно писать тесты вида

    1. public void testPreferenceIsSaved() throws Exception {
    2.  
    3.                 solo.sendKey(Solo.MENU);
    4.                 solo.clickOnText("More");
    5.                 solo.clickOnText("Preferences");
    6.                 solo.clickOnText("Edit File Extensions");
    7.                 Assert.assertTrue(solo.searchText("rtf"));
    8.                
    9.                 solo.clickOnText("txt");
    10.                 solo.clearEditText(2);
    11.                 solo.enterText(2, "robotium");
    12.                 solo.clickOnButton("Save");
    13.                 solo.goBack();
    14.                 solo.clickOnText("Edit File Extensions");
    15.                 Assert.assertTrue(solo.searchText("application/robotium"));
    16.                
    17.   }

    Подробности можно почитать тут code.google.com/p/robotium/w/list.

    Шаг 8. Тестирование на нескольких эмуляторах.

    1. При создании задания для Jenkins можно выбрать тип задания Build multi-configuration project.
    2. В разделе Configuration Matrix создаём оси для каждого изменяющегося параметра, например, разрешение и версия андроид и подставляем в настройки Run emulator with properties в виде ${resolution}. Посмотрите картинки по вышеуказанной ссылке, всё станет понятно.
    3. Остальные параметы указываем как в обычном задании.

    Подробности тут.

    Шаг 9. Подготовка релизной сборки.

    Релизную сборку собрать попроще, чем запустить тесты.

    1. Создаём в Jenkins задачу MyProjectRelease (тип Build a free-style software project).
    2. Как в шаге 6, указываем откуда тянуть исходники.
    3. Создаём Invoke Ant Build Step с параметарми:

      1. Targets:
      2.     release
      3. Build File:
      4.     MyProjectbuild.xml
      5. Properties:
      6.     sdk.dir=D:\android\android-sdk-windows
      7.     key.store=..\myproject.keystore (относительный путь к файлу-хранилищу ключа, сам ключ я положил в trunk)
      8.     key.alias=<alias>
      9.     key.store.password=<pass>
      10.     key.alias.password=<pass>

    4. Можно ещё настроить Archive the artifacts с Files to archive = ***-release.apk (если вы хотите бережно хранить все релизы и иметь возможность их скачивать через веб-интерфейс Jenkins).
    5. Для обфускации релиза при помощи ProGuard потребуется всего лишь добавить в project.properties (или в properties шага InvokeAnt задания в Jenkins) строчку proguard.config=proguard.cfg, где
      • proguard.config — имя переменной, в которой должно находиться имя файла с настройками для ProGuard,
      • а файл proguard.cfg автоматически создаётся Eclipse при создании проекта.

    Спасибо за внимание, надеюсь этот пост поможет сделать ваши программы чуточку лучше.

    Автор: bivy


    * - обязательные к заполнению поля


    https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js