Android Espresso wait for text to appear

后端 未结 3 1499
无人及你
无人及你 2020-12-06 12:17

I am trying to automate an Android app that is a chatbot using Espresso. I can say that I am completely new to Android app automation. Right now I am struggled with waiting.

3条回答
  •  情书的邮戳
    2020-12-06 13:17

    If the text that you're waiting on is in a TextView that won't enter the view hierarchy until after the sign-in is complete, then I suggest going with one of the other answers in this thread which operate on the root view (i.e. here or here).

    However, if you're waiting on the text to change in a TextView that is already present in the view hierarchy, then I would strongly suggest defining a ViewAction that operates on the TextView itself for better test output in the case of test failure.

    Defining a ViewAction that operates on a particular TextView instead of operating on the root view is a three-step process as below.

    Firstly, define the ViewAction class as follows:

    /**
     * A [ViewAction] that waits up to [timeout] milliseconds for a [View]'s text to change to [text].
     *
     * @param text the text to wait for.
     * @param timeout the length of time in milliseconds to wait for.
     */
    class WaitForTextAction(private val text: String,
                            private val timeout: Long) : ViewAction {
    
        override fun getConstraints(): Matcher {
            return isAssignableFrom(TextView::class.java)
        }
    
        override fun getDescription(): String {
            return "wait up to $timeout milliseconds for the view to have text $text"
        }
    
        override fun perform(uiController: UiController, view: View) {
            val endTime = System.currentTimeMillis() + timeout
    
            do {
                if ((view as? TextView)?.text == text) return
                uiController.loopMainThreadForAtLeast(50)
            } while (System.currentTimeMillis() < endTime)
    
            throw PerformException.Builder()
                    .withActionDescription(description)
                    .withCause(TimeoutException("Waited $timeout milliseconds"))
                    .withViewDescription(HumanReadables.describe(view))
                    .build()
        }
    }
    

    Secondly, define a helper function that wraps this class as follows:

    /**
     * @return a [WaitForTextAction] instance created with the given [text] and [timeout] parameters.
     */
    fun waitForText(text: String, timeout: Long): ViewAction {
        return WaitForTextAction(text, timeout)
    }
    

    Thirdly and finally, call on the helper function as follows:

    onView(withId(R.id.someTextView)).perform(waitForText("Some text", 5000))
    

提交回复
热议问题