Android unit tests explained — part 2

Yair Kukielka
3 min readFeb 28, 2016

--

In the previous post we saw that there are two types of unit tests in Android: instrumented and non-instrumented (or local). Please read it before moving on, so you fully understand the basics of unit testing in Android. We saw 3 low level unit test examples: a JsonParser, a FileSerializer and a SharedPreferences test.

In this article we are going to see how to access a test file (or asset) and a production file from our:

  • Instrumented tests: they are slow, only run on a real device or an emulator and live in the app/src/androidTest folder by default
  • Local or non-instrumented tests: they are very fast, run on your computer’s JVM and live in the app/src/test folder by default

1. Intrumented tests

For instrumented tests, I recommend you to place your assets or files in the assets folder, they will be easier to read from there.

First, we are going to read a file that’s in src/main/assets/myasset.txt

@Test
public void readAppAsset() throws Exception {
Context ctx = InstrumentationRegistry.getTargetContext();
InputStream is = ctx.getResources().getAssets().open("myasset.txt");
String s = Utils.readTextStream(is);
assertEquals("main myAsset", s);
}

And now, one that’s in src/androidTest/assets/myasset.txt

@Test
public void readTestAsset() throws Exception {
Context ctx = InstrumentationRegistry.getContext();
InputStream is = ctx.getResources().getAssets().open("myasset.txt");
String s = Utils.readTextStream(is);
assertEquals("androidTest myAsset", s);
}

Now you know how to read real assets from your app, and also test assets from the androidTest folder!

2. Local or non-instrumented tests

The non-instrumented code runs on the machine’s JVM. They are not related to Android, so those tests will use gradle’s default configuration. The default folder for test resources is src/test/resources. This is not an Android folder, but if you place your resources there, you’ll be able to access them from your non-instrumented unit tests like this:

@Test
public void readTestFile() throws Exception {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("myasset.txt");
String s = Utils.readTextStream(inputStream);
assertThat(s, notNullValue());
}

Another important concept is that test resources, will replace the app’s resources when they have the same relative path and name. For example, lets imagine we have these two files src/main/resources/myasset.txt and src/test/resources/myasset.txt, like this:

In our test, we will see the one in the src/test/resources folder. If we only had the file in src/main/resources then we would only see that one.

OK, that’s for when I have my resources in the resources folder, but what if I have them elsewhere? Now we’re going to see how to access files directly in the src/main/resources folder. Add this to your gradle file:

android {
...
sourceSets.test.resources.srcDirs += ["src/main"]
}

We just added the app’s src/main folder to our tests resources. Now we can launch this test and read the file src/main/assets/myasset.txt

@Test
public void readAppFile() throws Exception {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("assets/myasset.txt");
String s = Utils.readTextStream(inputStream);
assertThat(s, notNullValue());
}

And what if I want to read this file: src/test/myfiles/myfile.txt? In this case you can do it similarly, adding this to your gradle file:

android {
...
sourceSets.test.resources.srcDirs += ["src/test/myfiles"]
}

And the test would look like:

@Test
public void readTestMyFile() throws Exception {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("myfile.txt");
String s = Utils.readTextStream(inputStream);
assertEquals("test myfiles", s);
}

This is a little bit trickier, but you get the advantage of huge velocity since these run on the JVM and without a device!

This project is in Github. There are instructions in the README file. Happy unit testing!

--

--