Loading...
Loading...
Compare original and translation side by side
| What you need to prove | Test shape |
|---|---|
| Text, button, loading/error branch, conditional content | Plain UI Compose test |
| Callback wiring from click/input | Plain UI Compose test |
| Focus navigation or keyboard behavior | Compose test with key input |
| Visual layout, clipping, elevation, typography, image composition | Screenshot test |
| State holder updates UI correctly | State holder/unit test plus one wiring smoke test |
| Navigation, lifecycle, DI integration | Integration test |
| 需要验证的内容 | 测试类型 |
|---|---|
| 文本、按钮、加载/错误分支、条件内容 | 纯UI Compose测试 |
| 点击/输入的回调连接 | 纯UI Compose测试 |
| 焦点导航或键盘行为 | 带按键输入的Compose测试 |
| 视觉布局、裁剪、阴影高度、排版、图片合成 | 截图测试 |
| 状态持有者能否正确更新UI | 状态持有者/单元测试 + 一个连接冒烟测试 |
| 导航、生命周期、DI集成 | 集成测试 |
composeTestRule.setContent {
ProfileScreen(
state = ProfileUiState(name = "Ada", canSave = true),
onNameChange = {},
onSaveClick = { saved = true },
onBackClick = {},
)
}
composeTestRule.onNodeWithText("Ada").assertIsDisplayed()
composeTestRule.onNodeWithText("Save").performClick()
assertThat(saved).isTrue()composeTestRule.setContent {
ProfileScreen(
state = ProfileUiState(name = "Ada", canSave = true),
onNameChange = {},
onSaveClick = { saved = true },
onBackClick = {},
)
}
composeTestRule.onNodeWithText("Ada").assertIsDisplayed()
composeTestRule.onNodeWithText("Save").performClick()
assertThat(saved).isTrue()onNodeWithTextassertIsEnabledassertIsNotEnabledassertDoesNotExistonNodeWithTextassertIsEnabledassertIsNotEnabledassertDoesNotExistvar selectedId: String? = null
composeTestRule.setContent {
ItemList(
items = listOf(ItemUi("movie-1", "Movie")),
onItemClick = { selectedId = it },
)
}
composeTestRule.onNodeWithText("Movie").performClick()
assertThat(selectedId).isEqualTo("movie-1")runOnIdlevar selectedId: String? = null
composeTestRule.setContent {
ItemList(
items = listOf(ItemUi("movie-1", "Movie")),
onItemClick = { selectedId = it },
)
}
composeTestRule.onNodeWithText("Movie").performClick()
assertThat(selectedId).isEqualTo("movie-1")runOnIdleFocusRequestercompose-focus-navigationFocusRequestercompose-focus-navigationval requestedModels = mutableListOf<Any?>()
// Example helper, not a Compose API.
setContentWithFakeImageLoader { request ->
requestedModels += request.data
errorPainter()
}val requestedModels = mutableListOf<Any?>()
// Example helper, not a Compose API.
setContentWithFakeImageLoader { request ->
requestedModels += request.data
errorPainter()
}| Mistake | Fix |
|---|---|
| Constructing full app graph to test an error row | Test plain UI with |
| Testing click behavior through a ViewModel mock | Pass a callback and assert it was invoked |
| Screenshot test for simple text presence | Use semantics assertion |
| Semantics test for padding/color/focus ring | Use screenshot test |
| Test tags everywhere | Prefer text/content description/role when stable |
| UI test depends on real image loading/network/time | Fake or freeze the source |
TV/keyboard UI tested with | Use key input and focus assertions; see compose-focus-navigation |
| 错误做法 | 修复方案 |
|---|---|
| 构建完整应用图来测试错误行 | 使用 |
| 通过ViewModel mock测试点击行为 | 传入回调并断言其被调用 |
| 用截图测试验证简单文本存在 | 使用语义断言 |
| 用语义测试验证内边距/颜色/焦点环 | 使用截图测试 |
| 到处使用测试标签 | 当文本/内容描述/角色稳定时,优先使用它们 |
| UI测试依赖真实图片加载/网络/时间 | 模拟或冻结这些数据源 |
仅用 | 使用按键输入和焦点断言;参见compose-focus-navigation |