RoboSpock - Behavior Driven Development (BDD) for Android

Wojtek Erbetowski https://erbetowski.pl



Introduction

This article describes RoboSpock, a test framework for Android that provides an easy way of writing Behavior Driven Development (BDD) specifications with Groovy language and supports the Google Guice library. It combines two main solutions in the area: Robolectric and Spock framework.

Web Site: https://github.com/Polidea/RoboSpock

System requirements: Java SE 6

License & Pricing: Open Source under Apache2 licence

Motivation

Java development has come a long way to be where it is right now. Getting through the problems of early enterprise beans, fighting the hangover of heavy, stateful services and getting out of the clutches of xml-configuration-over-all corporate patterns was quite an adventure. Nowadays, playing nicely with alternative languages and modern frameworks to provide the pleasure of automated testing, writing pure business logic without a plethora of boilerplate code, you can look back at the Android platform with pity, as you can see many of these mistakes repeated.

I believe the lack of very important tools (e.g. Aspects Oriented Programming, BDD frameworks) is temporary and developed a way to bring one of the most powerful BDD frameworks, together with the mighty Groovy language [1] to the testing of Android applications. And this means testing with the greatest pleasure: writing blazing-fast, expressive unit tests.

This article brings to you two solutions at once: Robolectric [2], a testing library enabling running Android code on Java Virtual Machine (JVM), and Spock [3], a superb expressive test framework for Groovy. It presents, RoboSpock [4], the tool to glue them together. Enjoy the journey.

From writing tests to creating specification

Test Driven Development (TDD) is easy to learn, but hard to master [5]. There are many promises of TDD, like making fast, fearless changes, or building better architecture. But you have no chance of getting them or mastering the practice if you simply don't like writing tests. And if your environment is causing you mostly troubles you will hardly ever like it. And you should. This is why useful tools make the difference.

Spock framework is the new era BDD [6] framework. It provides handy tools for writing tests in given-when-then format, integrated mocking and parameterization. Since there is no better way to present a test framework than with examples, let's jump right into the middle of a sample specification.

def login activity initializes with non-null fields'() { given: def activity = new LoginActivity() expect: activity.onCreate(null) activity.$field" != null where: field << ['displayName, 'loginView] }

As you can see, Spock provides labels to separate different parts of your specification. This is a small thing that makes a huge difference: readable specifications with clean logical flow. The second thing is parameterization, the way you may specify parameters for independent test runs in Spock is the DRYest option you can get.

When you actually run this specification for LoginActivity class, that extends Android Activity base class it fails - java.lang.Exception: Stub! is what's every Android developers knows too well. This is how far we can get into testing Android on JVM. Not far enough, is it?

Classloaders for help

Why can't we run a single Android class locally? Because android.jar - a library provided to enable compilation with Java compiler - contains all of the interfaces, classes and statics, but not one implementation. The proper classes are provided by Android OS at runtime.

Since we are not able to run a single Android class outside of an Android device, because of failing static initialization blocks, we need to trick the runtime to use the implementation classes instead of the default stubs. The mechanism that allows us do that is called Classloader and is a part of Java since it's early times.

When running the test we may switch the system classloader to serve our classes instead of the original ones. To do that we need to provide an implementation class, a so-called shadow class that would shadow the stub and return a proper result.

Robolectric

Robolectric is a library that does exactly what's described above. It provides lots of reasonable implementation for Android classes (mostly moved from Android sources) in shadow classes. In addition it provides a classloader (built on top of Javassist library) to switch the classes at the time of class loading. Finally the embedded JUnit test runner encapsulates all that functionality into a test case.

The following JUnit test represents usage of Robolectric support to test the same thing as before, checking whether Activity properties were initialized with non-null values.

@RunWith(RobolectricTestRunner) class LoginActivityTest { @Test public void construstorShouldInitializeAllProperties() { // given LoginActivity activity = new LoginActivity(); activity.onCreate(null); // expect assertNotNull(activity.getMode()); assertNotNull(activity.getDisplayName()); assertNotNull(activity.getLoginView()); } }

Not so effective as before, but this allowed us to see the green bar! Now we might say that's enough. Robolectric doesn't provide any option to use Spock framework, but finally we are able to run a simple test on a JVM, which is fast enough to satisfy a regular TDD red-green-refactor lifecycle [7].

Meet RoboSpock

As you can see Spock is definitely an interesting tool. I believe there are not many people who choose to get back to the tools used before using Spock. Unfortunately it was unavailable for Android developers. Our need for such a tool led us to create Robolectric integration for Spock. This is how RoboSpock was born as a powerful tool, that lets you run simple specifications against your mobile application code and executes fast using IDE's support for JUnit tests (works on every modern IDE).

RoboSpock is available through Central Maven Repository and sources (with examples) are available on GitHub.

Capabilities

RoboSpock lets you work with Views, Activities, Async tasks, database and lots of other Android specific libraries. In addition of the tens of Robolectric built-in shadow classes, you can provide your own shadows to fill missing implementations or to simply adjust to your needs.

On the other hand RoboSpock gives you full access to Spock mechanisms, that means simple extension API, built in mocking support, descriptive parameterizations, readable structure and more.

RoboGuice and RoboSpock

There is no better partner for unit testing than the dependency injection design pattern. It lets you separate object under tests from the rest of the environment and focus on testing single module. Currently the most popular solution for Android development is RoboGuice [8], which is an Android mod of Google Guice [9] DI framework. That's the main reason why we decided to provide basic support for Guice tests in RoboSpock.

This code example presents the usage of creating Guice injector to provide Guice managed objects into the test.

class TaskActivitySpecification extends RoboSpecification { @Inject WebInterface webInterface def setup() { inject { install new TestTaskExecutorModule() bind(WebInterface).toInstance Mock(WebInterface) } } def "should display text from web"() { given: webInterface.execute(_) >> "Hi!" def taskActivity = new TaskActivity() when: taskActivity.onCreate(null) then: taskActivity.webTv.text == "Hi!" } }

Summary

The young RoboSpock library lets you work with beautiful Groovy specifications on a daily basis with you Android applications. Thanks to the glue work between Robolectric and Spock framework you are able to take advantage of both these tools and test your application without slightest complexes. I hope you find it helpful.

References

[1] http://groovy.codehaus.org/

[2] http://pivotal.github.com/robolectric/

[3] http://code.google.com/p/spock/

[4] https://github.com/Polidea/RoboSpock

[5] http://www.methodsandtools.com/archive/testdrivendevelopmenttraps.php

[6] http://dannorth.net/introducing-bdd/

[7] http://www.jamesshore.com/Blog/Red-Green-Refactor.html

[8] http://code.google.com/p/roboguice/

[9] http://code.google.com/p/google-guice/

More Software Testing Resources

Click here to view the complete list of tools reviews

This article was originally published in the Spring 2013 issue of Methods & Tools