Skip to content

Instantly share code, notes, and snippets.

@sierisimo
Last active December 14, 2018 01:02
Show Gist options
  • Save sierisimo/62009734d5abc3aaf8b6041fd4da8b74 to your computer and use it in GitHub Desktop.
Save sierisimo/62009734d5abc3aaf8b6041fd4da8b74 to your computer and use it in GitHub Desktop.
Common mistake when running espresso

What is this?

This is an small example of a common mistake I have seen in different projects and different developers.

Usually we, as developers, try to take the code to the more readable way but keeping steps clear.

But sometimes the steps we take for readability keep us away of the final purpouse. This is an example of it.

When trying to check if a view is or not visible we generally overuse allOf thinking it will do the match on the conditions we pass to it but surprisingly for some of us this does not work like that.

onView works like a (and I hope someone can correct me) lazy query for the hierarchy view, it only gets a matcher and tries to match when requested to it. How do we request it to match? Simple, just call perform or check.

What happens if we don't call perform or check? Actually, nothing. It only stays with like that. With an empty ViewInteraction that doesn't have problems because, well, it's just an empty element. No one is messing with it or asking anything, so there's no exception, no error, no warning.

What's in the example?

A problem:

  • You have an Activity (MainActivity.kt) which has a layout (activity_main.xml) and a test for a view tvAcMainHello in the activity. * The view is gone
  • In the test we do: onView(allOf(withId(R.id.tvAcMainHello), isDisplayed()))
  • We also try to: onView(allOf(withId(R.id.tvAcNotMainHello), isDisplayed())) (note the Not in the name, this is a different view).
  • We expect the test to fail in some cases here
  • Everything passes without problems… why?

How can we fix this?

Easy! Just remember what @chiuki has been telling us for (now) years:

onView(ViewMatcher)
  .perform(ViewAction)
  .check(ViewAssertion);

this means, that our common problem: onView(allOf(withId(R.id.tvAcNotMainHello), not(isDisplayed())))

Should be solved with:

onView(withId(R.id.tvAcNotMainHello).check(not(isDisplayed()))

And the hint in here is:

  • Keep your matchers as simple as possible. Remember: KISS
  • Remember the three steps: match -> perform -> check

Resources

Here's a video about it: https://www.youtube.com/watch?v=JlHJFZvZyxw

And here is the classic espresso cheat sheet: https://developer.android.com/training/testing/espresso/cheat-sheet

Keep the testing!

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tvAcMainHello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="@+id/tvAcNotMainHello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hi, Bye!"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
class MainActivityTest {
@get:Rule
val activityRule = ActivityTestRule<MainActivity>(MainActivity::class.java, false, true)
@Test
fun testVisibilityDoNotBreakTest() {
onView(allOf(withId(R.id.tvAcMainHello), isDisplayed()))
}
@Test
fun testVisibilityDoNotBreakTestAgain() {
onView(allOf(withId(R.id.tvAcMainHello), not(isDisplayed())))
}
@Test
fun willNotBreakTest() {
onView(allOf(withId(R.id.tvAcNotMainHello), isDisplayed()))
}
@Test
fun alsoWillNotBreakTest() {
onView(allOf(withId(R.id.tvAcNotMainHello), not(isDisplayed())))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment