android-test
android-test copied to clipboard
Espresso does not wait for AndroidX's ListAdapter's by default
Description
Included androidx.recyclerview.widget.ListAdapter performs asynchronous operations in the background. However, Espresso does not appear to be aware of it and thus tests can fail if async list diff is still diffing while Espresso starts inspecting views.
Steps to Reproduce
- Download RecyclerTest.zip
- Run ExampleInstrumentedTest couple of times, at least one test will fail eventually
Expected Results
Espresso should wait for built-in ListAdapter to finish diffing
Actual Results
Espresso does not wait and can fail the test
How come it is not resolved yet?
In the meantime I have managed to make a custom solution for it:
/**
* A solution for espresso execution to perform diffs on MainThread
*/
abstract class ThreadedListAdapter<T, VH : RecyclerView.ViewHolder>(
itemCallback: DiffUtil.ItemCallback<T>
) :
ListAdapter<T, VH>(
AsyncDifferConfig.Builder(itemCallback)
.apply {
if (isEspresso()) setBackgroundThreadExecutor(MainThreadExecutor())
}
.build()
)
/**
* This is a fork of internal MainThreadExecutor from [AsyncListDiffer]
*/
private class MainThreadExecutor : Executor {
val mHandler = Handler(Looper.getMainLooper())
override fun execute(command: Runnable) {
mHandler.post(command)
}
}
fun isEspresso(): Boolean {
return try {
Class.forName("androidx.test.espresso.Espresso")
true
} catch (e: ClassNotFoundException) {
false
}
}
and in the tests call:
InstrumentationRegistry.getInstrumentation().waitForIdleSync()