Rob*_*rdi 5 android-espresso android-jetpack-navigation android-jetpack-compose
我正在尝试为完全用 Compose 编写的 Android 应用程序编写集成测试,该应用程序具有单个 Activity 并使用 Compose 导航来更改屏幕内容。
我设法正确交互并测试导航图显示的第一个屏幕,但是,一旦我导航到新目的地,测试就会失败,因为它不等待 NavHost 加载新内容。
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<MainActivity>()
@Test
fun appStartsWithoutCrashing() {
composeTestRule.apply {
// Check Switch
onNodeWithTag(FirstScreen.CONSENT_SWITCH)
.assertIsDisplayed()
.assertIsOff()
.performClick()
.assertIsOn()
// Click accept button
onNodeWithTag(FirstScreen.ACCEPT_BUTTON)
.assertIsDisplayed()
.performClick()
// Check we are inside the second screen
onNodeWithTag(SecondScreen.USERNAME_TEXT_FIELD)
.assertIsDisplayed()
}
}
}
Run Code Online (Sandbox Code Playgroud)
我确信这是一个计时问题,因为如果我在Thread.sleep(500)之前添加onNodeWithTag(SecondScreen.USERNAME_TEXT_FIELD).assertIsDisplayed(),测试就会成功。但我想Thread.sleep()在我的代码中避免使用 s 。
有没有更好的方法来告诉composeTestRuleNavHost 在执行之前等待 NavHost 加载新内容assertIsDisplayed()?
PS 我知道单独测试可组合项会更好,但我真的想使用 Espresso 模拟应用程序上的用户输入,而不仅仅是测试可组合项行为。
正如这篇信息丰富的博客文章中所建议的,waitUntil可用于等待显示具有正确标签的节点:
// Waiting for the new destination to be shown
waitUntil {
composeTestRule
.onAllNodesWithTag(LogInTestTags.USERNAME_TEXT_FIELD)
.fetchSemanticsNodes().size == 1
}
Run Code Online (Sandbox Code Playgroud)
或者,添加一些糖后:
@RunWith(AndroidJUnit4::class)
class MainActivityTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<MainActivity>()
@Test
fun appStartsWithoutCrashing() {
composeTestRule.apply {
// Check Switch
onNodeWithTag(FirstScreen.CONSENT_SWITCH)
.assertIsDisplayed()
.assertIsOff()
.performClick()
.assertIsOn()
// Click accept button
onNodeWithTag(FirstScreen.ACCEPT_BUTTON)
.assertIsDisplayed()
.performClick()
// Waiting for the new destination to be shown
waitUntilExists(hasTestTag(SecondScreen.USERNAME_TEXT_FIELD))
// Check we are inside the second screen
onNodeWithTag(SecondScreen.USERNAME_TEXT_FIELD)
.assertIsDisplayed()
}
}
}
private const val WAIT_UNTIL_TIMEOUT = 1_000L
fun ComposeContentTestRule.waitUntilNodeCount(
matcher: SemanticsMatcher,
count: Int,
timeoutMillis: Long = WAIT_UNTIL_TIMEOUT
) {
waitUntil(timeoutMillis) {
onAllNodes(matcher).fetchSemanticsNodes().size == count
}
}
fun ComposeContentTestRule.waitUntilExists(
matcher: SemanticsMatcher,
timeoutMillis: Long = WAIT_UNTIL_TIMEOUT
) = waitUntilNodeCount(matcher, 1, timeoutMillis)
fun ComposeContentTestRule.waitUntilDoesNotExist(
matcher: SemanticsMatcher,
timeoutMillis: Long = WAIT_UNTIL_TIMEOUT
) = waitUntilNodeCount(matcher, 0, timeoutMillis)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5422 次 |
| 最近记录: |