【问题标题】:Android Instrumented testing asserting if an activity is startedAndroid Instrumented 测试断言是否启动了活动
【发布时间】:2019-09-22 11:42:15
【问题描述】:

我正在使用 Kotlin 编程语言开发一个 Android 应用程序。我正在将仪器测试添加到我的应用程序中。现在我正在尝试测试某个活动是否在延迟后开始。

这是我的活动代码。

class MainActivity : AppCompatActivity() {

    companion object {
        val LAUNCH_DELAY: Long = 2000
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Handler().postDelayed({
            this.startLoginActivity()
        }, LAUNCH_DELAY)
    }

    protected fun startLoginActivity()
    {
        startActivity(Intent(this, LoginActivity::class.java))
    }
}

我知道如何编写这样的简单测试

@Test
fun itRendersCompanyName() {
    onView(withId(R.id.main_tv_company_name)).check(matches(withText("App Name")))
}

但我在这里要测试的是 LoginActivity 是否在延迟后启动。我如何使用 Espresso 框架来做到这一点?

【问题讨论】:

    标签: android kotlin android-activity android-espresso instrumented-test


    【解决方案1】:

    你可以使用ActivityManager获取可见的Activity:

    inline fun <reified T : Activity> isVisible(): Boolean {
        val am = ApplicationProvider.getApplicationContext<Context>().getSystemService(ACTIVITY_SERVICE)
                as ActivityManager
    
        val visibleActivityName = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            am.appTasks[0].taskInfo.topActivity.className
        } else {
            am.getRunningTasks(1)[0].topActivity.className
        }
        return visibleActivityName == T::class.java.name
    }
    

    调用isVisible&lt;LoginActivity&gt;() 会告诉你LoginActivity 是否可见。

    另外,要等到您的LoginActivity 可见,您可以等待此方法获取true。例如:

    inline fun <reified T : Activity> waitUntilActivityVisible() {
        val startTime = System.currentTimeMillis()
        while (!isVisible<T>()) {
            Thread.sleep(200)
            if (System.currentTimeMillis() - startTime >= TIMEOUT) {
                throw AssertionError("Condition unsatisfied after $TIMEOUT milliseconds")
            }
        }
    }
    

    【讨论】:

    • 我建议在 appTasks getter 中检查 null:val visibleActivityName = am.appTasks.elementAtOrNull(0)?.taskInfo?.baseActivity?.className
    【解决方案2】:

    您可以为此使用Intents.intended()

    将以下内容添加到您的 build.gradle 文件中:

    androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0'
    

    在您的测试功能中,您可以尝试以下代码:

    Intents.init()
    Intents.intended(hasComponent(LoginActivity::class.java!!.getName()))
    

    您可以阅读有关 Espresso-Intents 的更多信息here

    【讨论】:

    • 嗨 Natig,我的项目中有三个不同的 Intent。我必须使用哪一个。他们都没有意图的方法。
    • 能否指定完整的类名或命名空间?
    • 您必须将androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0' 添加到您的应用级 build.gradle 文件中。
    • 这是类名,包名:androidx.test.espresso.intent.Intents
    • 不要忘记在调用预期()函数之前添加 Thread.sleep(2000),因为您的操作将根据您的代码在 2 秒后执行。
    【解决方案3】:

    最好用单元测试来测试这个状态。使用架构模式(例如 MVP/MVVM),模拟演示者/视图模型并检查触发了负责活动启动的方法

    【讨论】:

    • 如何在android中测试一个方法是否被触发?
    • Mockito.verify(mockedClass).someMethod(parameters)
    • 例如:在@Before:presenter = Mockito.spy(SomePresenter(...)) 在测试中:Mockito.verify(presenter, times(1)).startLoginActivity() where times(1 ) 意味着什么是一个交互
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    相关资源
    最近更新 更多