Functional Testing of the Android Webview using Java: How purity was invented

A long while ago, we decided to start doing native testing of Android, mostly because we found that we were fixing the same things over and over again on Android in Java.  While the Javascript quality was higher, the Java code was generally the same as when I first wrote PhoneGap back in 2008.  So, we started with manual tests.  Then I got creative and threw in some JUnit tests back when I started working on CordovaWebView.

However, there was something that was nagging us about the manual tests.  Many of these tests required us to click on user interfaces that were implemented in HTML and Javascript.  First we tried to adapt things such as WebDriver to test this, but we found that this was extremely complex to get working on Cordova, and we only ever managed to get an abandoned branch to work with the custom CordovaWebView.  At the end this was completely unmanageable, and we abandoned this work.

However, the tickets remained, such as ones like "Automate JQTouch Tab test" or "Automate iFrame Test".  The JQTouch one was abandoned because of these develpments, but along the way we discovered how to test the Android WebView using Java and JUnit.

The Android Test Framework gives you some very limited UI functionality tools.  These tools are designed for the Android UI and, they mostly consist of things like TouchUtils.  TouchUtils allows you to click in the middle of view like this:

touch.clickView(this, testView);

This may be super awesome for Android applications, but this sucks for things like Cordova, which is one giant view.  To prove this point, I ressurected some Canvas code that I wrote three years ago and I do some tests on it.


Above, you can see the click happen in the middle. It will always happen in the middle.  There is nothing that I can do to make it not happen in the middle.  This sucks.

I then googled around to see if I can get per-pixel support, and I found a blog post that showed this code:

long downTime = SystemClock.uptimeMillis();
// event time MUST be retrieved only by this way!
long eventTime = SystemClock.uptimeMillis();
Instrumentation inst = getInstrumentation();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, 300, 300, 0);

Now, this code is great, except that anyone who has done any Mobile Web Development knows that a pixel is not a pixel.  We have to factor in the screen density.  This is where purity comes in.

In purity, instead of giving the real pixels in Java, you pass in the WebKit pixels, and purity does the calculation required to do the touch where you want it.  The reason it's called purity is because it's simple, and it doesn't clutter up your Javascript with event handlers and injection code.  Eventually, this may be adapted to be a plugin so that purity code can be written in Javascript, but entirely run in Java.

For example, in purity, you would call this to do a touch event:

touchTool = new Purity(testActivity, getInstrumentation());
touchTool.touch(50, 200);

OK, where is the code:

The code is in the Cordova Android test directory on my personal branch here, and it is under org.apache.cordova.test.util. It'd be awesome if someone wanted to make this a third-party plugin, especially those people who have extreme pain with UI interaction on Android.