Hi,
I wrote earlier this year about my move to an Android team and how
surprised (shocked? disappointed?) I was at the woeful state of
android testing.
I embarked on a strategy of automated, black box testing using Appium
and Genymotion hoping that would solve the problem.
That turned out to be a partial success but now I know thats not
really a solution for 3 reasons:
1. The tests are really flaky. Every few runs the Genymotion emulator
would crash. Fixing this is not within my power. Also adb is
unreliable at times. I asked around (there are a few other teams doing
the same thing) and it turns out they use real devices and run the
tests against them manually. The teams are QA teams as opposed to
developers.
2. Turns out mocking the dependencies is really hard. External web
services are not too bad but my app communicates with a UPnP device on
the local wan. Its too difficult to mock it properly. It doesn't help
that documentation for the device is limited.
3. "Don't test your app through the UI". A lesson hard learned from my
web days. And thats what I was doing. If I had overcome the flakiness
issues I would then be faced with many long running tests that would
be hard to maintain. I'm reminded of JB Rainsberger's talk about
Integration tests are a scam(
http://vimeo.com/80533536). He's right
you know, I won't be able to cover all the tests needed to get full
coverage this way.
So back to basics I thought. We had some time so I convinced the team
to move to Android Studio. Took a bit of effort but we have it
working. Gradle builds. Nice and modern. IntelliJ as an IDE. I love
that IDE from my server side days. I got my key bindings back. I felt
good.
Right, unit testing. Thats the way to go. Make me feel better about
not having written any in months.
Crap, Google still only support Junit3. Tests look terrible,
unreadable. I have to teach my fellow devs how to write unit tests,
this was not going to fly.
Robolectric right? Thats what everyone is saying is the way to go on
Android. Been around for ages.
I started looking into using Robolectric with my project. Well now
that I'm using Android Studio, it should be easy. I Google'd around.
Then irony hit me in the face like a sucker punch.
I have to do WHAT to make it work? Hack the iml file! Thats rubbish
but maybe its a one-time deal. Nope, it turns out that I have to hack
it each time I introduce a new dependency. I did it anyway. The test
still didn't run in the IDE. It couldn't find the test class. Weird,
let me research some more.
So the fix is (and I'm not joking), run the test, copy and paste the
runtime classpath that was used by the IDE into a text editor. extract
the -classpath parameter (only a few thousand characters long), make
sure junit4 is first and add to the end the location of the test
classes directory. Then take this and pass as a parameter to the VM
during a test run.
WTF!
If something is this convoluted, you know it stinks. I can't do it. I
feel dirty. Its hard enough to convince my team that unit testing is
the professional thing to do and then show them this work around to
get it working? I would lose all credibility.
I remember watching the Google IO talk with the Android team. You
could see them squirming when asked about testing on Android. Why such
poor support for Robolectric considering the out of the box tools were
so poor? Why don't Google buy Genymotion as its a MUCH better emulator
than the stock Android one?
So my current plan? Create a pure Java module, move as much logic as I
can into it and write unit tests there (using Spock, my preferred unit
testing tool). I'll have to keep Android specific code in the main app
(untested) but hopefully it will be things like downloading
functionality that I can make generic and hope it works through manual
testing.
All the new libraries like Picasso, Retrofit, Rx Java, Otto, Dagger
are great but they need the Android SDK which means I won't be able to
write tests with them. Maybe I can get away with it with my approach.
Not sure.
Imagine a man, who has just experienced some tragedy, on his knees (in
the rain) looking up to the sky and saying "Why me God?". Of course he
gets no reply.
In the same vain, I ask "Tor, if my years of devotion to the
JavaPosse, since episode one (I'm a true believer) mean anything to
you, can you please tell me if there is a plan to make unit testing
easier in the future? If anyone knows its you. You work on Android
Studio!"
Of course I expect no reply.
But just maybe?
Rakesh