Using Espresso to Unit Test Google Maps

user2230304 picture user2230304 · Apr 28, 2015 · Viewed 9.3k times · Source

I am using Espresso to do some UI testing on my app. I have a fragment with a map, and I display some items on it that I get through a call to my backend.

When I click on a marker, I'm doing some UI things

Is there any way I can do unit testing on my map with espresso ?

Answer

kalin picture kalin · May 29, 2015

Short Answer: With espresso is not really possible. A solution might be to use UIAutomator: https://developer.android.com/tools/testing-support-library/index.html#UIAutomator https://developer.android.com/training/testing/ui-testing/uiautomator-testing.html

So you need to:

1) add gradle dependencies:

dependencies {
androidTestCompile 'com.android.support.test:runner:0.2'
androidTestCompile 'com.android.support.test:rules:0.2'
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1' }

2) make sure you add at least title to your markers even if you're not using it.

3) Write the test, code is smth like this:

UiDevice device = UiDevice.getInstance(getInstrumentation());
UiObject marker = device.findObject(new UiSelector().descriptionContains("marker title"));
marker.click();

Explanation:

GoogleMap generates UI and also makes it accessible i.e. map content can be seen as a tree of accessibility node info.

This is tree is a virtual view tree, it does not represent the real view tree. We will come to this later

By default the contentDescription of the map is "Google Map" and that of markers is "{markerTitle}. {markerSnippet}".

Then the question is so why not using espresso:

onView(withContentDescription("marker title. ")).perform(click()); ?

Because it won't find it, however :

onView(withContentDescription("Google Map")).perform(click());

will work just fine.

So how come UIAutomator works and Espresso doesn't?

Because they use different view trees.

UIAutomator uses tree of accessibility node info provided by AccessibilityService, while Espresso uses the view hierarchy and thus processes all children of any ViewGroup. The accessibility node info and the view hierarchy may or may not map one-to-one. In this case

onView(withContentDescription("Google Map"))

finds not a ViewGroup but a TextureView, which is not known to have children so Espresso cannot know what is drawn in there.

Voila! :)