android-test icon indicating copy to clipboard operation
android-test copied to clipboard

Espresso does not wait for AndroidX's ListAdapter's by default

Open matejdro opened this issue 6 years ago • 1 comments

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

  1. Download RecyclerTest.zip
  2. 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

matejdro avatar Jun 07 '19 06:06 matejdro

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()

MichalDanielDobrzanski avatar Jan 13 '22 14:01 MichalDanielDobrzanski