1

I have an Activity which has two Views - which are shown depending on the network condition.

  LinearLayout recyclerView = (LinearLayout) findViewById(R.id.recycler_view);
  LinearLayout errorParent = (LinearLayout) findViewById(R.id.error_parent);

  if(Utils.isNetworkAvailable()){
      recyclerView.setVisibility(View.VISIBLE);
      errorParent.setVisibility(View.GONE);
  }else{
      recyclerView.setVisibility(View.GONE);
      errorParent.setVisibility(View.VISIBLE);
}

I have written an Espresso test for testing Network conditions. Before running the test, I manually switch off the Internet.

ViewInteraction viewInteraction = onView(withId(R.id.recycler_view));
viewInteraction.check(matches(isDisplayed()));

Since there is no Internet, the recycler_view is GONE, and thus it is not present in the view hierarchy. But when running the code I am not getting NoMatchingViewException. Ideally when the view is not present in the hierarchy, I should get the above exception. Instead I am getting AssertionFailedError.

What is the reason for this behavior?

thedarkpassenger
  • 7,158
  • 3
  • 37
  • 61

2 Answers2

3

The best solution here is to look into source code of Espresso. Let's trace down, what is happening.

When calling check(final ViewAssertion viewAssert) in this line, the view is checked whether it is in the hierarchy. The exception NoMatchingViewException is not caught, because viewFinder finds the view in the hierarchy. Then the code goes to assertion. So the code goes funther to ViewAssertion's function: matches(final Matcher<? super View> viewMatcher) with missingViewException being null. In this line noViewException is null, therefore code goes to assertThat. The assertion is isDisplayed(), which measures global effective visibility of the view. This is where AssertionFailedError is thrown.

For asserting wherther the view is not in visible in the current layout another construction should be used:

onView({Matcher<View>}).check(doesNotExist());

or

onView({Matcher<View>}).check(matches(not(isDisplayed())));

More explanation about it here

Community
  • 1
  • 1
R. Zagórski
  • 20,020
  • 5
  • 65
  • 90
  • Thanks for the detailed answer. I debugged by going through the steps which you mentioned and clearly Espresso is able to find the view in the hierarchy in this line targetView = viewFinder.getView(), which returns targetView as non null. But if I go through UIAutomator, it does not show recycler_view in the hierarchy. So ideally it should not get the view here as well. – thedarkpassenger Dec 15 '16 at 09:09
  • So I will assume that if the view was present in the hierarchy, and afterwards the visibility of the view has been set to GONE, then Espresso won't throw NoMatchingViewException. – thedarkpassenger Dec 15 '16 at 09:13
0

In my opinion is this is appropriate behavior. Your view is existing in your view hierarchy, is just not visible. You should get:

AssertionFailedWithCauseError: 'is displayed on the screen to the user' doesn't match the selected view.
Expected: is displayed on the screen to the user 
Leśniakiewicz
  • 874
  • 1
  • 10
  • 21
  • But when we set the visibility of a view to GONE, doesn't android remove the view from the hierarchy. Even in the UIAutomator, I am not able to find the view. – thedarkpassenger Dec 15 '16 at 09:11