I am writing UI Automation tests in Espresso for Android & came across a scenario for which I haven't got any solution so far.
In one Fragment
, I have OptionsMenu
with a single item. The state of that MenuItem
is set according to value from API response.
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.clear();
getActivity().getMenuInflater().inflate(R.menu.menu_cancel_order, menu);
MenuItem cancelMenuItem = menu.findItem(R.id.cancel_order);
if(something) { // something can be a boolean value from server
cancelMenuItem.setEnabled(true);
} else {
cancelMenuItem.setEnabled(false);
}
}
For UI testing, I need to write test case for checking whether this MenuItem
is enabled/disabled.
For clicking on the overflowmenu,
ViewInteraction actionMenuItemView = onView(
allOf(withId(R.id.action_settings), withContentDescription("Settings"), isDisplayed()));
actionMenuItemView.perform(click());
And so far what I have tried to check the Assertion is given below.
onView(allOf(withText("Cancel Order"), withId(R.id.cancel_order))).check(matches(not(isEnabled())));
But this fires NoMatchingViewException
with message
NoMatchingViewException: No views in hierarchy found matching: (with text: is "Cancel Order" and with id: com.equinix.ecp.betatest:id/cancel_order)
So I tried changing it to
onView(allOf(withText("Cancel Order"))).check(matches(not(isEnabled())));
Somehow this matched the view but it was not a MenuItem but the TextView inside the MenuItem & since I am setting setEnabled()
to MenuItem, check()
Assertion won't work as expected since it is a TextView
.
So my question is how to write Test for checking enabled/disabled state of MenuItem.
One simple way to check for a View or its subclass like a Button is to use method getVisibility from View class. I must caution that visibility attribute is not clearly defined in the GUI world. A view may be considered visible but may be overlapped with another view, for one example, making it hidden.
The most used assertion is the matches() assertion. It uses a ViewMatcher object to assert the state of the currently selected view. onView(...). check(matches(withText("Hello!")))
Espresso testing library extends the necessary JUnit classes to support the Android based instrumentation testing.
it would be a good idea to make use of uiautomatorviewer, to put a breakpoint in at the point your test fails, and then inspect your app's layout for clues
it sounds to me that you have two views. One with the id of R.id.cancel_order
and another with text "Cancel Order"
which probably has another id (or could/should).
So together they return NoMatchingView, because they aren't the same view.
They could be sibling views, or possibly one is a descendent of another. This is where uiautomatorviewer is very handy for figuring out what's happening on screen
as long as you've installed "Android SDK Platform-Tools" and "Android SDK Tools" from Terminal:
cd /Users/<user name>/Library/Android/sdk/tools/bin
./uiautomatorviewer
(it's also helpful to save this as a script and just use an alias shortcut for convenience)
as for your matcher, i would try :
onView(allOf(
withId(R.id.cancel_order),
hasSibling(withText("Cancel Order"))
)).check(matches(not(isEnabled())));
or change hasSibling(_)
to hasDescendent(_)
or isDescendentOfA(_)
, depending on their relationship (which you can find out by using uiautomatorviewer)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With