Search code examples
androidkotlinandroid-espressokotlin-extension

Kotlin and Android Espresso tests: Adding extension function with receiver


I'm still working on improving my understanding of extension functions with receivers and need some help of you experts on a question I have regarding this.

I have an Android Espresso testcase where I check that I have selected the items of a recyclerview. This is the same code repeated many times. I was wondering if it would be possible using kotlins extension functions with receiver to simplify this.

My test code now:

@Test
public void shouldSelectAll() {
    ...
    onView(withRecyclerView(R.id.multiselectview_recycler_view).atPosition(0))
            .check(RecyclerViewMatcher.isSelected(true));
    onView(withRecyclerView(R.id.multiselectview_recycler_view).atPosition(1))
            .check(RecyclerViewMatcher.isSelected(true));
    onView(withRecyclerView(R.id.multiselectview_recycler_view).atPosition(2))
            .check(RecyclerViewMatcher.isSelected(true));
}

Is it some how possible to create a function atPositions(varag positions: Int) that would take an integer array and call the assertion on each of the positions in the array. Like this:

@Test
public void shouldSelectAll() {
    ...
    onView(withRecyclerView(R.id.multiselectview_recycler_view).atPositions(0, 1, 2))
            .check(RecyclerViewMatcher.isSelected(true));
}

Solution

  • Sure!

    private fun Int.matchAsRecyclerView(): RecyclerViewMatcher = withRecyclerView(this)
    
    private fun RecyclerViewMatcher.checkAtPositions(vararg indices: Int, assertionForIndex: (Int) -> ViewAssertion) {
        for(index in indices) {
            onView(this.atPosition(index)).let { viewMatcher ->
                viewMatcher.check(assertionForIndex(index))
            }
        }
    }
    

    Which should work as

    R.id.multiselectview_recycler_view.matchAsRecyclerView().checkAtPositions(0, 1, 2, assertionForIndex = { 
        index -> RecyclerViewMatcher.isSelected(true) 
    })