为什么 compose ui 测试的 IdlingResource 会阻塞主线程?

发布于 2025-01-12 12:18:47 字数 2123 浏览 2 评论 0原文

我编写了一个“最小”AS 项目来复制我面临的问题。 这是 gh 链接

我正在尝试在我的仅撰写项目中编写端到端 ui 测试。测试涵盖简单的登录 ->同步数据->转到主视图用例。

这是整个测试:

@HiltAndroidTest
class ExampleInstrumentedTest {

    @get:Rule(order = 1)
    val hiltRule = HiltAndroidRule(this)

    @get:Rule(order = 2)
    val composeTestRule = createAndroidComposeRule<MainActivity>()

    @Inject
    lateinit var dao: DummyDao

    val isSyncing = mutableStateOf(false)

    @Before
    fun setup() {
        runBlocking {
            hiltRule.inject()
            dao.deleteAllData()
            dao.deleteUser()
        }

        composeTestRule.activity.isSyncingCallback = {
            synchronized(isSyncing) {
                isSyncing.value = it
            }
        }

        composeTestRule.registerIdlingResource(
            object : IdlingResource {
                override val isIdleNow: Boolean
                    get() {
                        synchronized(isSyncing) {
                            return !isSyncing.value
                        }
                    }
            }
        )
    }

    @Test
    fun runsTheStuffAndItWorks() {
        composeTestRule
            .onNodeWithText("login", ignoreCase = true, useUnmergedTree = true)
            .assertIsDisplayed()
            .performClick()

        composeTestRule
            .onNodeWithTag("sync")
            .assertExists()

        composeTestRule.waitForIdle()

        assertFalse(isSyncing.value)

        composeTestRule.onRoot().printToLog("not in the list")

        composeTestRule
            .onNodeWithTag("the list", useUnmergedTree = true)
            .assertIsDisplayed()
    }
}

测试运行“正常”,直到它应该等待同步工作线程完成其工作并最终导航到“主可组合项”。

不幸的是,当空闲资源不空闲时,测试似乎会阻塞设备的 ui 线程,当空闲资源变得空闲时立即完成测试。

我尝试过直接使用 Espresso 的 IdlingResource,但这也不起作用,显示了类似的结果。我也尝试过在不同的点添加 compose 的 IdlingResource ,但这也不起作用(在导航调用之间添加一个也会阻塞 UI 线程,并且测试更快失败)。

我在这里做错了什么?我是否忘记设置一些东西?

I've written a "minimal" AS project to replicate my the problem I'm facing. Here's the gh link.

I'm trying to write an end-to-end ui test in my compose-only project. The test covers a simple sign-in -> sync data -> go to main view use case.

Here's the whole test:

@HiltAndroidTest
class ExampleInstrumentedTest {

    @get:Rule(order = 1)
    val hiltRule = HiltAndroidRule(this)

    @get:Rule(order = 2)
    val composeTestRule = createAndroidComposeRule<MainActivity>()

    @Inject
    lateinit var dao: DummyDao

    val isSyncing = mutableStateOf(false)

    @Before
    fun setup() {
        runBlocking {
            hiltRule.inject()
            dao.deleteAllData()
            dao.deleteUser()
        }

        composeTestRule.activity.isSyncingCallback = {
            synchronized(isSyncing) {
                isSyncing.value = it
            }
        }

        composeTestRule.registerIdlingResource(
            object : IdlingResource {
                override val isIdleNow: Boolean
                    get() {
                        synchronized(isSyncing) {
                            return !isSyncing.value
                        }
                    }
            }
        )
    }

    @Test
    fun runsTheStuffAndItWorks() {
        composeTestRule
            .onNodeWithText("login", ignoreCase = true, useUnmergedTree = true)
            .assertIsDisplayed()
            .performClick()

        composeTestRule
            .onNodeWithTag("sync")
            .assertExists()

        composeTestRule.waitForIdle()

        assertFalse(isSyncing.value)

        composeTestRule.onRoot().printToLog("not in the list")

        composeTestRule
            .onNodeWithTag("the list", useUnmergedTree = true)
            .assertIsDisplayed()
    }
}

The test runs "alright" up to the point where it should be waiting for the sync worker to finish its job and finally navigate to the "main composable".

Unfortunately, the test seems to be blocking the device's ui thread when the idling resource is not idle, finishing the test immediately as the idling resource does become idle.

I've tried using Espresso's IdlingResource directly, which also didn't work, showing similar results. I've tried adding compose's IdlingResource in different points as well, but that also didn't work (adding one between navigation calls also blocks the UI thread and the test fails even sooner).

What am I doing wrong here? Am I forgetting to setup something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文