Thursday, February 3, 2011

How to work on Robolectric in parallel with another project

The Robolectric framework is designed to allow us to create and install test doubles for elements of the Android API as we encounter the need for them during our test and development activities. This should come as no surprise since Robolectric was born of an Agile development environment that strives to create software artifacts on the basis of demonstrated need rather than speculation. A consequence of this approach is that the most effective way to work with Robolectric is to also work on Robolectric. When your project encounters a part of the Android API that is not yet covered by Robolectric, or which is not covered in a way that you like, it is easy to add the needed functionality to Robolectric and move forward. This is similar to writing a new mock object in order to facilitate testing except that the new functionality is added to the permanent test infrastructure rather than being inlined into the test code.

The Robolectric documentation contains instructions about how to write and modify the Shadow Classes that serve as the test doubles for the Android code, but little is said about how to integrate active Robolectric development into your working environment. This article addresses how to obtain and build the Robolectric source so that your changes are immediately visible to your tests; how to track upstream changes to Robolectric; and how to create pull-requests for code that you want to contribute to the Robolectric project. These instructions are completely compatible with the instructions for registering your own private Shadow Classes contained in the Robolectric documentation about customizing the RobolectricTestRunner. So, you will still be able to write Shadow Classes (including subclasses of existing ShadowClasses) that are specific to your own application and register them in your custom TestRunner at the same time as you are writing new classes, or other extensions to Robolectric functionality, that are meant for consumption by the wider Robolectric community.

About git
The source code for Robolectric lives in a public git repository on the GitHub website. Unfamiliarity with git should not be an obstacle to using a live version of the Robolectric source in your project. This article documents all of the commands that are needed and GitHub has excellent help for both git and GitHub including how to install git on Windows. Git does have a couple of idiosyncrasies, almost always for good reasons, and we will discuss them as we run into them.  The first of these is that it is a distributed revision control system which means that there are multiple copies of the repository. In our case there will be three repositories in addition to your working copy of the code. The first repository lives on GitHub and is the primary repository for the Robolectric code. The second repository will also live on GitHub and will be the primary repository for your organization's copy of the Robolectric source code and your gateway for sharing contributions that you wish to share with the community. The third repository lives on your personal development machine and is the one that sometimes catches people by surprise. This article will treat it as just a gateway between your machine and GitHub, but it is a fully fledged revision control system for the work done on a single instance of a project on a single machine. With that information in mind we can proceed.

Forking Robolectric
The first thing you need to do is to create a place on GitHub for the changes you want to make. You don't have to use GitHub as your revision control solution for Robolectric if you don't want to, but you do need a way to move code between your organization and the main Robolectric repository and this is the mechanism for doing that.
  1. Login or create an account on GitHub. You may want to create a separate account for your specific organization or project.
  2. Navigate to the Robolectric project page at:
  3. Click the button that says "Fork" (upper right corner, third line from the top, fourth button from the right)
    You now have your own private copy of the Robolectric source code in a repository in GitHub that knows how to track changes in the main Robolectric repository. Later we'll talk about how to merge changes from the main Robolectric repository into your own, and how to request that we pull some or all of the changes you've made into the main repository so that they can be used and maintained by the rest of the community.
  4. Click on the button with the clipboard icon next to the text that says: "This URL has Read+Write access"
    This will copy a URL to your clipboard that can be used to make a local clone of the repository
  5. On the command line, go to the location where you want the Robolectric project to be created (you do not have to create the subdirectory for it), type: "git clone " and then paste in the URL you just obtained. The command should look something like this:
    git clone
    When this command completes you will have a local copy of the Robolectric repository (in
    robolectric/.git) as well as a working copy of the code in the newly created robolectric directory.
  6. To build and test Robolectric type the following commands:
    For Maven builds:
    ant maven-install-jars
    mvn install

    This will locate your Android development kit and install android.jar into your local Maven repository and then build Robolectric, test it, and then install the resulting jars into Maven.
    For ant builds:
    ant clean test
    Which will build the Robolectric jar and run the tests.
Adding Robolectric as a Dependency in Your Project
If you are using Maven you should take note of the Robolectric version (currently 0.9.9-SNAPSHOT) from pom.xml file and add a dependency to your projects pom.xml that looks something like this:


The easiest thing to do is to include the Robolectric sources as part of your compile.tests target something like this:



Where the key items are the addition of <src path="..robolectric/src/main/java"> as one of the source directories and <fileset dir="../robolectric/lib/main" includes="*.jar"> in the classpath.

Eclipse and IntelliJ
As mentioned elsewhere both of these IDEs can import Robolectric using its pom.xml file. In Eclipse this is done using the M2Eclipse plugin. In the "Configure Build Path" dialog for your test project, under the Projects tab, just add Robolectric and any changes you make to the Robolectric project will be picked up. Similarly in IntelliJ, Robolectric can be added as a module by navigating to the "Project Structure" dialog, selecting "Modules" under "Project Settings" and then clicking the plus icon and navigating to the pom.xml file.

Pulling Upstream Changes
From time to time you will want to pull the changes that have been made to the main Robolectric repository into your own workspace. The following command will connect the two together in order to make that possible:

git remote add pivotal

This makes pivotal an alias for the main repository. Now you can pull down the latest Robolectric sources and merge them with your local changes with:

git pull pivotal master

If you have made substantial changes to the Robolectric code you may need to resolve merge conflicts before proceeding further. Ensure that all of the tests run with this command:

mvn clean test

Submitting Pull Requests
Once your changes to Robolectric are complete and the tests for them are all passing, you will often want them to become a permanent part of the Robolectric codebase so that they can be used and maintained by the rest of the community. You can accomplish this by pushing your changes to your repository on GitHub and submitting a pull request to the Robolectric team.

The first step in this process is to get the code in your repository to look the way you want the code in the Robolectric repository to look. Start by pulling in any upstream changes, as described above, and ensuring that the entire test suite passes. Once everything is working the next step will be to commit your changes to your local repository in preparation for pushing them to GitHub. This is accomplished with the following command:

git commit -a -m"some commit message"

In this command the -a means "add all of the changes I've made to the list of changes to be committed" and the -m allows you to put your commit message on the command line. If it is omitted git will open an editor and ask you to enter your commit message there.

Ensure that all of your changes have made it into your repository:

git status

The resulting message should tell you which branch you are on and that there is nothing to commit.

Once your changes are in your local repository you can push them to the GitHub repository with the following command:

git push origin master

This command may fail if you have not set up an SSH key for your GitHub account. If that happens, these instructions will help you out.

Running git push makes it possible for the Robolectric team to get access to the changes that you want to add. You can request that we add these changes to the project by submitting a pull request from the GitHub website. Log in to GitHub and select the forked Robolectric repository from your list of repositories on the right-hand side of the page, and then click on the "Pull Request" button from the button bar in the upper right corner. Fill in the form to let us know what to expect from your pull-request and then click the "Send Pull Request" button. We like to use pull request titles as story names in Tracker so please make yours suitably descriptive.

We are responsive as possible to pull requests, often putting them ahead of our current priorities, in order to encourage the Robolectric community to remain active. Many factors, including the presence of passing tests, commitments of our day jobs, compatibility with our roadmap, and technical and legal considerations, can affect our ability to quickly address each pull request. Regardless of our ability to respond, we want everyone who makes a contribution to Robolectric to know that we, and the rest of the community, appreciate their efforts very much, and give our heartfelt thanks for all of the great contributions we have already received.