Robolectric, Ivy, Maven repo drama
For those of you who know me (which would include most people reading this post) you’ll note that I am a huge proponent of TDD and proper project hygiene. I describe project hygiene as the things you do to ensure a successful project with easy maintenance. I have recently been working to prototype such a project in Android but have been hitting several roadblocks along the way. Hi, I’m Cliff. You’re here because you want a nicely structured project. I’m here because I can’t seem to get my project in the right shape, so I’m complaining.
I started a while ago with an example chat app I had written as a guide to using IntelliJ to write Android apps. I even put up a video tutorial on the subject. I recently had been working to reuse my example which had a hard dependency on the Robolectric project. Robolectric is a cool toy that lets you perform REAL unit tests on Android. There are those who may say, I do unit tests all the tim using Robotium, or the Android JUnit packages… but these are not unit tests as they involve either the emulator or a physical device. The tests I have written run successfully on my laptop and take a fraction of the time that typical Android tests take.
I had my environment working about 7-8 months ago but so much has changed since then. Today when I tried to recreate my magic I had trouble trying to “install” Robolectric on my new Mac. (All my work had been setup on my old Mac.) I originally tried running with the older 1.1 Robolectric jar but then had to tweak my IDE envirnment variables to point to ANDROID_HOME which is so much fun on Mountain Lion these days. (It’s practically impossible to get IntelliJ to see custom system environment variables and the launchctl trick doesn’t work for me.) So the nI eventually decided after forcing ANDROID_HOME and getting a path not found on “~/android-sdk-macosx/platforms/android-10″ since my new Mac doesn’t have the older SDKs to install a later version of Robolectric. My thinking was, “maybe they’ve ironed out the details and finally fixed it so you don’t need env variable settings and older SDKs…”
If you visit the Robolectric home page you’ll see all the installation instructions point to a Maven POM. that does you no good if you’re starting from an existing Android project because it either
a.) Forces you to refactor your project using Maven standards
b.) Forces you to reverse engineer the pom to find out where the actual Robolectric jar is.
Both of these options are terrible for existing Android work and since many people rarely get to work on green field this presents a tough dilemma.
I eventually found a way to work around the issue by whipping up an equivalent ivy.xml and throwing together a custom_rules.xml to use in my Android project but it still sux on the surface because of the extra overhead involved with declaring a single Maven dependency in an Android project.
Step 1: create a custom_rules.xml.
Step 2: declare an Ant “-pre-build” target that performs the ivy resolve task and writes the dependecy jar files to your project’s “./libs” folder.
Step 3: create a custom ivy.xml that declares your Maven dependencies.
Step 4: Cuss because you realize it’s not trivial to invoke your custom “-pre-build” target in isolation to test your new configuration.
Step 5: Create a custom “ivy-resolve” target which your new “pre-build” target should now depend on.
Step 6: Test your “ivy-resolve” in isolation to ensure it pulls the correct dependencies.
Step 7: Cuss because your IDE’s built-in version of Ant does not include the Ivy jar.
Step 8: Either find the Ivy jar hidden on your hard drive and dump it into your IDE’s antlib or find your custom ant build tools and point your IDE to that.
Step 9: Repeat step 6
step 10: Cuss because your project’s “libs” folder has now exploded with unnecessary transitive dependencies including everything from ant to maven-model.jar to wagon to xerces.jar
step 11: Try to run your tests and realize that the dependencies declared don’t line up with the examples from the web site.
step 12: construct a blog post expressing your frustrations with the current state of Android development.
In the end I’m wondering why, in the year 2013, we can’t do any better out of the box. Why is it still a chore to practice proper TDD on mobile platforms? (I’m glaring at the iOS community as well because I don’t think that camp is any closer to out of the box TDD.) I would love to just open my IDE, click on a unit test, perform some hotkey combo Cmd+shift+F10 or something, and watch either red or green bars stretch across the screen without considering silly stuff like my environment, grabbing older SDKs, researching dependency matrices and the like.
By the way, I found out how to pull external dependencies into an Android project following this blog post. Nice little trick!