Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/208.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Espresso-如何检查视图是否已准备好单击_Android_Testing_Android Espresso_Ui Testing - Fatal编程技术网

Android Espresso-如何检查视图是否已准备好单击

Android Espresso-如何检查视图是否已准备好单击,android,testing,android-espresso,ui-testing,Android,Testing,Android Espresso,Ui Testing,我有一个带有splashscreen的应用程序,它可以停留大约2秒钟 之后,它将切换到另一个活动A。 在A中,我在ASeekBar中设置了一个值,然后单击按钮进行确认 当我开始录制浓缩咖啡测试时,它会在屏幕上播放。因此,当它试图设置SeekBar值或单击按钮时,我得到一个nomatchingvieweexception。所以我第一次尝试解决这个问题就是简单地添加一个sleep(5000)。这起作用了 然而,我不想在每次活动切换后都进行手动睡眠 因为这似乎是不必要的代码 因为这意味着运行测试需要不

我有一个带有splashscreen的应用程序,它可以停留大约2秒钟

之后,它将切换到另一个活动
A
。 在
A
中,我在A
SeekBar
中设置了一个值,然后单击
按钮进行确认

当我开始录制浓缩咖啡测试时,它会在屏幕上播放。因此,当它试图设置
SeekBar
值或单击
按钮时,我得到一个
nomatchingvieweexception
。所以我第一次尝试解决这个问题就是简单地添加一个
sleep(5000)
。这起作用了

然而,我不想在每次活动切换后都进行手动睡眠

  • 因为这似乎是不必要的代码
  • 因为这意味着运行测试需要不必要的等待时间
  • 定时可能是任意的,并且对于不同的设备可能不同
  • 所以我试着检查我是否参加了正确的活动/是否能看到正确的视图。我使用了一些SO链接:和

    然而,即使这样也不能100%起作用

    我有两个功能:

    fun <T: AppCompatActivity> waitForActivity(activity: Class<T>, timeout: Int = 5000, waitTime: Int = 100) {
        val maxTries = timeout / waitTime
        var tries = 0
    
        for(i in 0..maxTries) {
            var currentActivity: Activity? = null
            getInstrumentation().runOnMainSync { run { currentActivity = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(
                Stage.RESUMED).elementAtOrNull(0) } }
            if(activity.isInstance(currentActivity)) {
                break
            } else {
                tries++
                sleep(waitTime.toLong())
            }
        }
    }
    
    这两种方法都不能100%奏效。它们似乎都在超时限制内返回,并且“找到”了活动/视图。但是,预期的视图,例如
    按钮
    尚未准备好执行,例如
    元素。执行(单击())
    。它不会导致异常
    NoMatchingViewException
    ,但也不会执行我所做的单击。对于
    SeekBar
    ,我使用以下方法:

    private fun setSeekValue(seekBar: ViewInteraction, age: Int) {
            val fullPercentage = .9f
            val step = 1/99f
    
            seekBar.perform(
                GeneralClickAction(
                    Tap.SINGLE,
                    CoordinatesProvider { view ->
                        val pos = IntArray(2)
                        view?.getLocationOnScreen(pos)
                        FloatArray(2).apply {
                            this[0] = pos[0] + view!!.width * (.05f + fullPercentage*step*age)
                            this[1] = pos[1] + view.height * .5f
                        }
                    },
                    PrecisionDescriber {
                        FloatArray(2).apply {
                            this[0] = .1f
                            this[1] = 1f
                        }
                    },
                    InputDevice.SOURCE_MOUSE,
                    MotionEvent.ACTION_BUTTON_PRESS
                )
            )
        }
    
    但是,当我使用这些函数并在其之后放置一个很短的睡眠(例如
    sleep(100)
    )时,它就工作了。然而,这又与上面列出的三个原因背道而驰,我在这里试图避免这三个原因

    正如您在函数
    waitForView
    中看到的,我尝试使用
    hasWindowFocus()
    检查视图是否“可用”。但这仍然不会执行单击,除非我再次在其后面放置
    sleep(80)
    或其他内容。因此,它等待splashscreen切换到
    A
    ,找到它要查找的视图,然后无法执行单击,除非我稍等一下

    我还尝试了
    查看
    的以下功能:

    • 我迷路了
    • 伊肖恩
    • 可见度
    • getDrawingRect
    • 可聚焦
    • 专注
    • IsLayoutDirection已解决
    他们两个都没有像我预期的那样工作。对于所有这些,在
    元素上返回所需的值后。检查
    waitForView
    部分,如果不在之后放置一个短的
    睡眠
    ,它们仍然无法访问

    是否有方法可靠地检查我是否可以单击视图/安全地执行
    ViewInteraction.perform()

    或者通过检查活动是否已完全加载到其视图可用的位置。或者直接检查视图是否可用

    private fun setSeekValue(seekBar: ViewInteraction, age: Int) {
            val fullPercentage = .9f
            val step = 1/99f
    
            seekBar.perform(
                GeneralClickAction(
                    Tap.SINGLE,
                    CoordinatesProvider { view ->
                        val pos = IntArray(2)
                        view?.getLocationOnScreen(pos)
                        FloatArray(2).apply {
                            this[0] = pos[0] + view!!.width * (.05f + fullPercentage*step*age)
                            this[1] = pos[1] + view.height * .5f
                        }
                    },
                    PrecisionDescriber {
                        FloatArray(2).apply {
                            this[0] = .1f
                            this[1] = 1f
                        }
                    },
                    InputDevice.SOURCE_MOUSE,
                    MotionEvent.ACTION_BUTTON_PRESS
                )
            )
        }