Gradle

Integrating ErrorProne and NullAway with an Android project

2017-09-15 Android, Gradle, Java, Static Code Analysis No comments

Recently, with the remote help of guys from Uber in California, I integrated NullAway and ErrorProne with the one of my open-source Android projects.

What is NullAway?

Basically, it’s a tool to help eliminate NullPointerExceptions (NPEs) in your Java code. It detects situations where NPE could occur at the compile time.

Let’s have a look at the following code:

static void log(Object x) {
    System.out.println(x.toString());
}
static void foo() {
    log(null);
}

NullAway will find out that we’re passing null and we’ll get appropriate error message:

warning: [NullAway] passing @Nullable parameter 'null' where @NonNull is required
    log(null);
        ^

It’s good to have checks like that because they eliminate possible bugs in advance and follows Clean Code principles.

A few words about ErrorProne

NullAway is built as a plugin to ErrorProne and can run on every single build of our code. Moreover, ErrorProne can perform other checks on our code, which can find out commonly people mistakes. E.g. it can detect a situation, where programmer forgot to add @Test annotation in the unit test method in a test suite and other things. It has built-in bug patterns, which are used during code analysis.

Integration with the Android project

I’ve integrated ErrorProne and NullAway with ReactiveNetwork Android library.

First, in the main build.gradle file, I’ve added the following lines:

ext.deps = [
            ...
            nullaway          : 'com.uber.nullaway:nullaway:0.1.2',
            errorprone        : 'com.google.errorprone:error_prone_core:2.1.1',
            ...
            ]

buildscript {
  repositories {
    jcenter()
    maven {
      url 'https://plugins.gradle.org/m2/'
    }
  }
  dependencies {
    ...
    classpath 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.11'
    classpath 'net.ltgt.gradle:gradle-apt-plugin:0.11'
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
  }
}

Next, in the library/build.gradle file, I’ve added appropriate plugins in the top:

apply plugin: 'net.ltgt.errorprone'
apply plugin: 'net.ltgt.apt'

Afterwards, I could add dependencies:

dependencies {
  ...

  annotationProcessor deps.nullaway
  errorprone deps.errorprone
}

The last thing to do, is the task responsible for running analysis during project compilation:

tasks.withType(JavaCompile) {
  if (!name.toLowerCase().contains("test")) {
    options.compilerArgs += ["-Xep:NullAway:ERROR", "-XepOpt:NullAway:AnnotatedPackages=com.github.pwittchen.reactivenetwork"]
  }
}

That’s it! Now, I could run analysis by typing:

./gradlew check

and fix the issues.

I think, a quite similar approach and configuration could be applied to a regular, pure Java project built with Gradle.

If you’re interested in the complete configurations, check it out in my project at: https://github.com/pwittchen/ReactiveNetwork.
You can also view Pull Request #226 made by @msridhar (kudos for him!).

Building and running SAP Hybris Commerce Platform via Gradle

2017-09-01 Gradle, Hybris 1 comment

Introduction

I really like Gradle build system for JVM apps. It has flexibility like Ant and great dependency management capabilities like Maven. It addition, it doesn’t use XML notation, but Groovy programming language, so builds configurations are simple, concise, easier to read and easier to create. In my opinion, Gradle is truly modern build system for JVM apps. Nevertheless, there are projects, which are pretty old and use older systems like Ant. For example, all Hybris projects are based on Ant. Moreover, they have their custom setup and configurations, internal extensions system, etc. I was wondering if it’s possible to migrate Hybris Platform build from Ant to Gradle. That’s why I created a simple Proof of Concept.

Migrating from Ant to Gradle

If we want to use Gradle, we need to install it first.

sudo apt-get install gradle         # if we're on Ubuntu Linux
brew install gradle                 # if we're on macOS

For more details and instructions for other systems, check official Gradle installation guide.

Then, we need to go to our Hybris platform directory and navigate to hybris/bin/platform

After that, we need to initialize gradle inside this directory by running gradle command.
Next, we need to create gradle wrapper by running gradle wrapper command.
Now we should have the following elements in our directory:

  • .gradle (directory)
  • graldew (wrapper file for Unix)
  • gradlew.bat (wrapper file for Windows)

Afterwards, we can create build.gradle configuration file.

It should have the following contents:

ant.importBuild 'build.xml'
apply plugin: 'java'

repositories {
  jcenter()
}

task run() {
  doLast {
     exec {
          executable "./hybrisserver.sh"
      }
  }
}

task cleanGeneratedDirs(type: Delete) {
  delete "../../data"
  delete "../../log"
  delete "../../roles"
  delete "../../temp"
}

task cleanConfig(type: Delete) {
  delete "../../config"
}

dependencies {
  compile fileTree(dir: 'lib', include: ['*.jar'])
}

Now, we can execute the following command:

./gradlew clean build

and platform will be built.

In order to initialize the platform, we can call:

./gradlew initialize

If we want to start the Hybris server, we can simply call:

./gradlew run

To clear directories generated during build and initialization, we can run:

./gradlew cleanGeneratedDirs

I tried to make clean task dependent on this one, but I got a few errors and didn’t spend too much time on investigating them.

As you probably noticed, this solution is just a wrapper around Ant build defined in build.xml file and it’s not pure Gradle build configuration. Nevertheless, these tips may be useful for the people who need to have custom build configurations and dependencies. There’s no doubt that creating and maintaining configurations via Gradle is much easier and more convenient than doing the same job via Ant.

Summary

As we can see, it’s possible to migrate Hybris build from Ant to Gradle, but please remember that Hybris has a custom setup and it may not be the best decision in each case. We should always consider pros and cons of such solution and adjust it to our needs. In legacy systems, we often have to stick to existing setups because making “revolution” may be a huge overhead and doesn’t have to pay off. Moreover, all Hybris extensions also have build configurations based on Ant. On the other hand, I can highly recommend Gradle for greenfield JVM projects.

References

There’s another nice, short article describing migrating Java projects from Ant to Gradle: Easily Convert from Ant to Gradle (objectpartners.com).

Unit test coverage report with Travis CI for Robolectric on Android

2017-03-19 Android, Continuous Integration, DSP2017, Gradle, Unit Tests No comments

Introduction

Some time ago, I’ve written an article about Test coverage report for Android application. It got some interest (many comments below article and many visits according to Google Analytics), so I decided to refresh this topic. Previously, I’ve written instrumentation unit tests, which needed to be executed on a real device or an emulator. It’s a good approach when you want to test functionalities strongly connected with the device. E.g. when you want to test operations on a real SQLite database or something like that. Nevertheless, this approach has huge disadvantages. It’s hard to run tests on the Continous Integration server because we need to have the emulator or device up & connected all the time and also tests need to interact properly with the device to get passed what is not so easy. In most cases, mocking part of the application’s behavior is enough. In that case, we can easily run tests on a CI server and have deterministic test results. In order to do that, we can use Robolectric.

Gradle configuration

First, we have to add appropriate dependency to jacoco-android plugin in our top-level build.gradle file:

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:2.3.0'
    classpath 'com.dicedmelon.gradle:jacoco-android:0.1.1'
  }
}

Next, we need to add appropriate test dependencies in another build.gradle file for our app or library.

dependencies {
  testCompile 'junit:junit:4.12'
  testCompile 'com.google.truth:truth:0.32'
  testCompile 'org.robolectric:robolectric:3.1.2'
  testCompile 'org.mockito:mockito-core:2.7.17'
}

I’ve added also dependencies to JUnit, Truth and Mockito library, which are used in my tests.

We also need to add appropriate plugins:

apply plugin: 'jacoco'
apply plugin: 'jacoco-android'

To avoid ignoring our tests by the coverage report, we need to configure the following settings:

android {
  testOptions {
    unitTests.all {
      jacoco {
        includeNoLocationClasses = true
      }
    }
  }
}

Next, we need to configure report output:

jacocoAndroidUnitTestReport {
  csv.enabled false
  html.enabled true
  xml.enabled true
}

Travis CI configuration

We are done with Gradle configuration. I’m assuming we have Travis CI build configured. If you don’t know, how to do this, visit travis-ci.org and enable builds for your project. It’ pretty easy. Now, we should visit codecov.io website, register there (e.g. with GitHub account) and add our project. After that, we need to add the following items to our .travis.yml file:

after_success:
  - bash <(curl -s https://codecov.io/bash)

script:
  - ./gradlew clean build test jacocoTestReport check

Here we are performing clean, build an application, running unit tests, generating test coverage report with Jacoco and performing check (Lint, FindBugs, PMD & CheckStyle).

Writing unit tests with Robolectric

Next we can place our tests in src/test/ directory.
Sample unit test can look as follows:

In my case, I also needed to create src/test/resources/robolectric.properties file with the following content:

sdk=23

because Robolectric didn’t work with the Android SDK newer than 23. Moreover, I also needed to use Robolectric v. 3.1.2, because I had problems with running tests and generating coverage report with the latest version of the Robolectric.

Summary

When we have everything configured, we can push our tests to the GitHub repository, Travis CI build will be triggered and we can beautiful test coverage report, which can help to improve our tests.

We can also click on the main package and see detailed coverage information for the several packages.

Moreover, we can analyze coverage change in time.

I’ve applied approach described in this article in ReactiveNetwork open-source library. If want to see the complete solution, take a look at the source code of this project or see its coverage report on-line.

Installing release and debug version of app on a single device

2014-12-25 Android, Gradle No comments

Introduction

During software development process developers and QAs may want to have installed release and debug version of the app on a single device, what can be very helpful when they want to develop and use application at the same time. Another advantage is the fact that debug and release version of the app may need different configuration. It this post I will show you an example in which we are changing application name and launcher icon, but we can also change different values during compilation in the same way (e.g. address of the webservice). Some time ago, I’ve created similar template, but it was using older version of Build Tools, Android SDK and Android Studio. I’ve created new template, with the newest version of Android Studio (1.0.2) and newest version of Build Tools (1.0.0), so in that case, build.gradle file is smaller and simpler, but does its work correctly.

Exemplary repository

You can find exemplary project template at: https://github.com/FutureProcessing/android-debug-release-template.
All important information are included in README.md file and build.gradle file with project configuration.

Important files:

Source of essential build.gradle file presenting main idea is as follows:

Java Gradle Template

2014-10-17 Gradle, Java No comments

Some time ago, I had some troubles with configuring Java project with Gradle in IntelliJ IDEA CE. There is possibility to create new Gradle project in mentioned IDE, but for some reason it didn’t worked out-of-the box in my case on Ubuntu. I wanted to have pure, clean Java project with Gradle build system ready to open in IntelliJ IDEA. I found well configured simple project at: https://github.com/quinnliu/SampleGradleProject. Basing on that project, I created my simple template. I modified this project a little bit, added FEST assertions and wrote a few Unit Tests. In addition, I configured main class in build.gradle file in order to execute it via ./gradlew run command. My project template also has gradle wrapper, which is very convenient practice.

You can find my project template at: https://github.com/pwittchen/java-gradle-template
If you want to compile project, run the following command: ./gradlew clean build
If you want to start tests, run the following command: ./gradlew test
Actually build command will run tests as well.
If you want to run application, use the following command: ./gradlew run.
You can also run application, tests or start compilation from the IntelliJ IDEA IDE.

I hope, you will find that template useful and handy.

Different build config for debug and release version of the Android app

2014-10-08 Android, Gradle No comments

Sometimes we may want to set different address of the back-end web service for debuggable and release version of our Android app. E.g. predefined static host and port for release version of the application and our local IP address and predefined port for debuggable version of the application. In second case, we can deploy back-end webservice on our local machine for testing purposes. We can customize all of that in build.gradle file. We can use variant.buildType.isDebuggable() instruction to check build type of the app. I described way of Updating Android XML resources before compilation via Gradle in one of my previous posts, so you can check it if you don’t understand replaceBackendAddressInResources(variant, host, port) method. After proper configuration, setting of the back-end url is straightforward. Please check the code between // configuration of the back-end address - begin
and // configuration of the back-end address - end comments.

Now, you can create release and debug version of the app with different addresses of the web service what is very useful during the process of development and deployment of the project. We can use this trick also for setting different parameters depending on our needs.

Versioning Android applications

2014-09-13 Android, Gradle No comments

When we work in a team projects, our code constantly changes and being tested. Often some bugs occur in a specific version of application and no longer exists in next version of the project, because one programmer might fixed the bug according to the Boy Scout Rule and this is good. Nevertheless, sometimes we need to write documentation and check in which version bug occurred to be sure, that it was really fixed. In addition, QA Engineer needs to know, which version of the project he or she should check.
That’s why we should introduce versioning system to our project. In Android Manifest we have versionCode and versionName. The versionCode is used for updates on Google Play Store and it has to be integer value. We should increment versionCode before releasing new version of the application for the users. The versionName available in Android Manifest is a string value and we can use it to store information, which we need in a current project. When we use Git as a Version Control System, we can put SHA value of a specific commit into our version name. In addition, we can add date and time of compilation to this variable. After that, our versionName contains very detailed information about current version of our application. Exemplary versionName will look in as follows: f935ea7-20140913144001.

We can obtain that with proper configuration of build.gradle file containing buildTime() method and gitSha() method.
Please, take a look at creation of versionName in 35th line of the build.gradle file presented below.

Updating Android XML resources before compilation via Gradle

2014-09-10 Android, Git, Gradle 2 comments

Problem

In a team project, we encountered one of the common problems connected with mobile applications. Android application sends requests to backend web service and we don’t have backend web service deployed right now on a separate server, so every mobile developer is compiling and running backend web service on the local machine for testing purposes. In the beginning, url of backend url looked as follows:

Of course address varies on different machines.

When every developer was pushing changes, configuration of the backed url changed as well. It became annoying, so we decided to do something about that.

Solution

Attempt #1

First, we came with an idea of ignoring local changes of the XML file, which contains backend url address.
It can be done via Git in the following way:

git update-index --assume-unchanged [<file>...]

We can undo this operation with such command:

git update-index --assume-unchanged [<file>...]

We can also add ignored alias to our .gitconfig file:

[alias]
ignored = !git ls-files -v | grep "^[[:lower:]]"

Then we can type: git ignored to display ignored files.

For more information check StackOverflow discussion.

This solution is kind of work-around, so we decided to do it better.

Attempt #2

We could create alias for backend url and replace it before compilation dynamically via Gradle.

Our new configuration file res/values/configuration.xml looks like that:

Then, our build.gradle file needed to be updated. The most important part starts in 29th line, where #const_backend_url# value is replaced with an IP address of the local machine, where mobile application is compiled. As I mentioned before, backend web service application is compiled on the same machine, so backend web service address will be proper in that case for testing purposes.

Similar trick was applied in project: https://github.com/nenick/android-gradle-template in file https://github.com/nenick/android-gradle-template/blob/master/App/build.gradle, so you can check it out.