29

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 ?

user2230304
  • 578
  • 1
  • 5
  • 14
  • For `Google maps Espresso test`, please check [here](https://code.google.com/p/android-test-kit/wiki/EspressoSamples#Matching_data_using_onData_and_a_custom_ViewMatcher) – bjiang Apr 28 '15 at 19:00
  • Could you please give me a quick example of a click on a Marker? – user2230304 Apr 29 '15 at 14:09
  • Sure, take look [here](https://github.com/jbj88817/GoogleMap-InfoWindow-android) and [here](https://github.com/jbj88817/GoogleMapExample-android) at my github – bjiang Apr 29 '15 at 16:28
  • 1
    @bjiang , not clear what to do with your samples. Can you update the read me file to make it easier? I.e. where is the code that selects the marker? – HRVHackers Apr 14 '16 at 04:28
  • 2
    @bjiang link (and its redirect) is broken. – nasch Aug 29 '18 at 14:59

1 Answers1

71

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! :)

fede1608
  • 2,808
  • 1
  • 16
  • 17
kalin
  • 3,546
  • 2
  • 25
  • 31
  • 12
    Thank you, answer is very clear. I'm very surprised something as basic as map testing is not natively possible with Espresso. – user2230304 May 29 '15 at 08:27
  • 1
    This works good!, although it doesn´t work when I run all the tests with ./gradlew connectedAndroidTest, it has to be run as a single test – Jesus Almaral - Hackaprende Feb 03 '17 at 16:47
  • i believe the issue would not be with this approach rather the way you run all the tests. If you provide me with an issue with more details I would be happy to help :) – kalin Feb 03 '17 at 16:59
  • I've the same issue of @JesusAlmaral I simply run all the cases from android studio which is equivalent to ./gradlew connectedAndroidTest. – Islam Salah Feb 27 '18 at 08:26
  • Again it depends on what other tests do and behavior of the app. Try to put waits/timeouts or use clickAndWaitForNewWindow if this is the case – kalin Feb 27 '18 at 12:48
  • It turns out that the uiautomator loses focus of the screen. To get the screen focus I simply call the method `uiDevice.pressRecentApps()` twice. – Islam Salah Mar 14 '18 at 14:56
  • Not sure if the case, but remember when running more than one test you have to check the before and after scenario situation, so that it is comaptible and equal every time you run a scenario. @djodjo – Ricardo F. Nov 28 '18 at 11:42