You are viewing our old blog site. For latest posts, please visit us at the new space. Follow our publication there to stay updated with tech articles, tutorials, events & more.

Continuous Integration for Android apps

4.00 avg. rating (85% score) - 1 vote
By : Minni Arora

Three years ago, Naukri launched a campaign titled ‘Naukri on Mobile’. In order to establish mobile presence and for broader accessibility to the target audience, free job search apps on mobile for smartphones were introduced. Ever since then, the traffic from mobile applications is just rising.
With more and more features getting built into the app and the team expanding, both unit and integration testing came to the force. Unit testing is well established as a good practice for Web development, but is usually left behind when developing mobile apps. It is in fact more important for mobile apps because once your app is published and users have installed it, the bugs remain until you release a fix. With every release, you have to wait for it to get approved, then wait for users to install the update. This isn’t the Web, where you fix a page and it’s instantly available to the world. In the meantime, you can easily end up with unhappy users and bad reviews that will remain with you for a long time.
So, a typical workflow looks like,
  1. Write a new unit test case
  2. Add/modify code to pass the test case
  3. Execute the test case locally on the emulator/device and confirm that the test case passes
  4. Execute the complete test suite locally on the emulator/device and confirm that no other test cases are failing
  5. Commit the code into Git
Instead of having an engineer set up the environment and run the test suites manually and avoid the chances of him forgetting to execute them, we needed a Continuous Integration server to monitor the repository. That is where we started using Jenkins. With each commit or at regular intervals, the server automatically checks out the sources onto the integration machine, initiates a build, runs the unit and integration tests and notifies the result of the build. Thus, it ensures that any changes that go into source control, do not break the build.
The first and foremost step to CI is to follow the key principles,
  1. Get a source code management system like SVN or Git
  2. Everyone commits to the mainline frequently to detect conflicts early
  3. To overcome environmental differences every commit should build the mainline on an Integration machine. If the mainline build fails, it needs to be fixed right away
Installing Jenkins was easy. Platform specific instructions are available on their website. With Jenkins up and configured, the objective was to achieve the following,
  1. Generate builds automatically for QA
  2. Run Unit and Integration tests and publish results
  3. Measure code coverage
  4. Measure code quality using Lint
Building project with Ant
The android sdk comes equipped with support for Ant. It is a simple tool to compile and build projects. The android apk file is generated by the following steps,
Adding build.xml to the main project
android update project -p <PATH to your main project>
Build the main project. For CI we build in debug mode
ant clean debug
This will generate .apk file in the /bin directory. This can be archived or emailed using Jenkins interface.
Running Unit and Integration tests
After the main project, we build the test project.
Adding build.xml to the test project
android update test-project -m <PATH to your main project> -p <PATH to your test project>
Start the emulator and run the test suite from within test project
ant clean debug install test
All of these can be configured as build steps in Jenkins.
But where are the test reports ?
The steps above will generate .apk file, install it on emulator and run the test suite and the test results are visible in Jenkins console. To generate test reports in JUnit format, we will need a custom test runner. We can use android-junit-report. Just download it and configure the Android test project to use this test runner rather than the default instrumentation runner.  
By default, the test runner will store its output to some location like /data/data/${}/files. We can define an Ant target to use adb pull and copy the files to Jenkins workspace.
<target name=”pull-test-report”>
      <mkdir dir=”junitreports”/>
      <exec executable=”${adb}” failonerror=”true”>
      <arg line=”${adb.device.arg}”/>
      <arg value=”pull” />
      <arg value=”/data/data/${}/files/junit-report.xml” />
      <arg value=”junitreports/junit-report.xml” />
So, now we say,
ant clean debug install test pull-test-report
Code Coverage Using Emma
From the several tools available for code coverage analysis we use EMMA, an open-source toolkit for measuring and reporting Java code coverage that is supported by the Android project, and the infrastructure to start using it is already there, therefore minimizing the effort needed to implement it.
When we run ant clean debug install test pull-test-report, the coverage report gets created in /bin directory. This report can be recorded and displayed as a post build action in Jenkins,

Code Quality Using Lint
The Android SDK provides a code scanning tool called lint that helps to easily identify and correct problems with the structural quality of your code, without having to execute the app. The Jenkins plugin for lint parses XML reports produced by running lint, analyses them and displays the results for each build. Information shown includes a build summary, list of issues and trends.
Thus, an automated workflow looks like,
  1. Code is committed into Git/SVN
  2. Jenkins job is invoked for a defined branch which performs the following
    1. Build code
    2. Run UTs and ITs
    3. Publish reports
  3. If UT failures threshold is reached, fail the build and send email to responsible developers
  4. Generate tag from branch revision
  5. Build APK
  6. Deploy on emulator
  7. Run functional tests on emulator and mail the report to QA teams
By automating the build process and running the tests on a regular basis, we reduce bugs and simplify and accelerate the process of shipping great apps.
Posted in General