Check out our Bootcamp Schedule View Schedule

Triumph! Android Studio 1.2 Sneaks In Full Testing Support

Jason Atwood

I’m calling it. We’ve been monitoring the state of testing in the Android world for some time now, waiting for the day when testing would be fully baked into the Android development cycle. Well, that day has finally arrived.

I wrote about setting up unit testing in Android Studio back in January. If you were committed enough to get through the whole post, you’ll remember how tedious the setup was. We knew that better testing tools were in the works—the measures I described in my previous post were just a stopgap.

Today, all of those workarounds are completely unnecessary, thanks to the Android Tools team. Android Studio 1.2, which is currently in beta, removes any need for third-party workarounds or custom hacks to Robolectric. The groundwork was introduced in Android Studio 1.1, which was released back in February. It included an experimental setting to enable unit testing. Last week with the beta release of 1.2, that setting is no longer experimental. It’s baked right in to Android Studio. While the Nerds here at the Ranch are quite surprised that nary a word was mentioned in the release notice for v1.2, unit testing support is here to stay.

Today I’d like to walk through the greatly simplified steps to set up unit testing in Android Studio. I’ll then go back and explain how to transition away from the more complicated approach I described in January.

Fresh Setup

The unit testing how-to post that accompanied the Android Studio 1.1. release is no longer valid for Android Studio 1.2. The only step we need to take is to select the correct Build Variant Test Artifact:

build variant test artifact

That’s it! We can now add our test dependencies and get to writing tests. Our build.gradle file looks like this:

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

    ...

    testCompile 'junit:junit:4.12'
    testCompile('org.robolectric:robolectric:3.0-rc2') {
        exclude group: 'commons-logging', module: 'commons-logging'
        exclude group: 'org.apache.httpcomponents', module: 'httpclient'
    }
}

Robolectric 3.0

The keen reader will notice that we’re relying on Robolectric’s current release candidate for v 3.0. We’ve tested this new feature in Android Studio against Robolectric 2.4, and it works as well. However, you will need to use a custom RobolectricTestRunner (see my prior post). Robolectric provides a nice guide on upgrading from 2.4 to 3.0.

A convenient addition to Robolectric 3.0 is an extension of RobolectricTestRunner specifically designed for Gradle command line or Android Studio, called RobolectricGradleTestRunner. We can now annotate our test classes:

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, emulateSdk = 21)
public class MyActivityTest {

    @Before
    public void setUp() throws Exception {
        // setup
    }

    @Test
    public void testSomething() throws Exception {
        // test
    }
}

Finally, we can run our tests as Gradle Tests from within Android Studio! [Editor’s note: see below for changes in Android Studio.]

run tests menu item

That’s all there is to it. Now you have immediate feedback on all passing and failing tests right inside Android Studio.

passing_tests

Transition From Previous Workaround

If you followed my previous post, most of the transition requires removing existing code:

  • Remove the JC&K plugin from project-level build.gradle
classpath 'com.github.jcandksolutions.gradle:android-unit-test:2.1.1'
  • Remove Evan Tatarka’s Unit Test plugin from Android Studio’s plugin list and the module-level build.gradle:
apply plugin: 'android-unit-test'
  • Remove the fix for Android Studio 0.8.9 from the module-level build.gradle file:
afterEvaluate {
    tasks.findByName("assembleDebug").dependsOn("testDebugClasses")
}
  • If you upgrade to Robolectric 3.0, remove your custom RobolectricTestRunner and use RobolectricGradleTestRunner:
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, emulateSdk = 21)
public class MyActivityTest { ... }

Can it be all so simple? Yes! Check out Josh Skeen’s demo for a working implementation. It’s time to write some great tests and elevate the quality of your Android apps. Show us how you’re using Robolectric and the new testing support to write great tests.

Warning: Test Events Were Not Received

Updated May 15: Several commenters noted that they had some issues when repeatedly running their tests. Here’s how to avoid the “Test events were not received” error.

We need to have Gradle re-run all of our individual tasks each time we run our tests. This is because Gradle tries to optimize our task by identifying individual subtasks that don’t need to be re-run.

Initial run:

...
:app:compileDebugUnitTestJava
:app:compileDebugUnitTestSources
:app:mockableAndroidJar UP-TO-DATE
:app:assembleDebugUnitTest
...

Re-run:

....

:app:compileDebugUnitTestJava UP-TO-DATE
:app:compileDebugUnitTestSources UP-TO-DATE
:app:mockableAndroidJar UP-TO-DATE
:app:assembleDebugUnitTest UP-TO-DATE
...

Unfortunately, Android Studio needs all of these tasks to be run. Otherwise, it will not know to respond to the running of our tests, and we’ll get a “Test events were not received” warning. We can force Gradle to re-run all tasks by updating our run configurations:

edit configuration dialog

Updates to Android Studio 1.3

Updated December 2015: Several commenters noted that they had some issues finding the “Run -> Gradle” test option in newer versions of Android Studio. Here’s what’s changed and how to fix it.

Android Studio has merged the JUnit and Gradle test options into just JUnit, so you just need to select Run 'MyActivityTest'

Select "Run MyActivityTest"

Once you run a test, you’ll probably hit the error:

java.lang.RuntimeException: build/intermediates/bundles/debug/AndroidManifest.xml not found or not a file; it should point to your project's AndroidManifest.xml

All you need to do is update JUnit’s working directory. You can do this per-test or per-project, but I prefer to just do it for all projects as an Android Studio default. Open up Run/Debug Configurations, navigate to Defaults -> JUnit. Then select Configuration tab. Then next to Working directory, select MODULE_DIR.

Android  Studio update build config

Nothing else from the initial post needs to change. You’ll still rely on RobolectricGradleTestRunner.

Not Happy with Your Current App, or Digital Product?

Submit your event

Let's Discuss Your Project

Let's Discuss Your Project