Tuesday, February 26, 2013

Robolectric 2.0 alpha 2

I'm happy to announce the second alpha version of Robolectric 2!

As before, this release is alpha-quality, and targeted at early adopters. We expect that there'll be bugs. We expect APIs to change before final release. Please use this alpha only if you can deal with some churn.

Big thanks to Square and Pivotal for giving us time to work on this.


Changes since alpha 1:

  • Classes in the android support lib are now fully enabled without the use of shadows.
  • Resource loading is better than ever. Library project support is much more robust.
  • Internally we've switched from Javassist to ASM for the bytecode manipulation that works Robolectric's magic. This and a couple other optimizations give us a huge performance win: one project's test suite here at Square dropped from 163 seconds to 76.
  • We report our Build.VERSION.SDK_INT as 8 (Froyo) for now.
  • Should get along well with ActionBarSherlock.


Changes coming soon:

  • Removing even more shadows (most non-JNI Android classes should work without much shadowing) and enabling more of the SDK.
  • Easier TestRunner setup and configuration.
  • Performance and memory use improvements.
  • Ability to switch Android SDK level on a per-test basis.


Use it!

If you've been using Robolectric 1.x, see my blog post on migrating to Robolectric 2.0.

If you're new to Robolectric, just add this to your pom:
<dependency>
  <groupId>org.robolectric</groupId>
  <artifactId>robolectric</artifactId>
  <version>2.0-alpha-2</version>
</dependency>
Add a @RunWith to your test class and you're ready to go!
@RunWith(RobolectricTestRunner.class)
public class MyActivityTest {
  ...
}

Caveats:

Currently only android.support.v4's Fragments and LruCache are supported. Support for the core android Fragments and LruCache from later SDK versions will be coming soon. As a workaround, you should be able to use the support versions for now.


Help:

If you find bugs, make an issue on our github project and label it with robolectric-2.

Migrating to Robolectric 2.0

There are several changes in Robolectric 2.0 that will require modifications to existing projects that use the 1.x versions. Here are some quick notes on migrating your Robolectric 1.x-based test suite to 2.0-alpha-2.

Update your pom.xml

Robolectric's maven groupId changed from com.pivotallabs to org.robolectric:
  <dependency>
    <groupId>org.robolectric</groupId>
    <artifactId>robolectric</artifactId>
    <version>2.0-alpha-2</version>
  </dependency>

Package rename

Robolectric moved from com.xtremelabs.robolectric to org.robolectric. A simple search and replace in your code should do the trick:

$ cd my-project-dir
$ find . -name \*.java | xargs -n 10 \
  sed -i.bak 's/com\.xtremelabs\.robolectric/org.robolectric/g'


Update your TestRunners

If you've subclassed RobolectricTestRunner, you'll need to remove some constructors and override some different methods than before. RobolectricTestRunner and related configuration will be overhauled significantly for 2.0-alpha-3, so if you're doing extensive customization you might want to wait until then to upgrade.

If that doesn't scare you off, here's a template for customizing the test runner in alpha-2:

public class MyTestRunner extends RobolectricTestRunner {
  public MyTestRunner(Class<?> testClass) throws InitializationError {
    super(RobolectricContext.bootstrap(MyTestRunner.class, testClass,
        new RobolectricContext.Factory() {
          @Override
          public RobolectricContext create() {
            return new RobolectricContext() {
              // override methods here to customize things...
            };
          }
        }));
  }
}

Specifying qualifiers

In Robolectric 1.x, there were a few ways to goad it into loading resources other than the defaults, including calling setLayoutQualifierSearchPath() on a ViewLoader (and occasionally it worked). In Robolectric 2, the easiest way is to put a @Values annotation on your test:

@Test @Values(qualifiers = "fr-land")
public void shouldShowBucolicFrenchLandscape() throws Exception {
  // ...
}