为什么 compose ui 测试的 IdlingResource 会阻塞主线程?
我编写了一个“最小”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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论