英文:
In Unit Compose UI test, OutlinedTextField exists but is not displayed
问题
我在单元测试中测试了一个名为 OutlinedTextField 的组件。当我运行应用程序时,文本字段始终显示出来。但是,当我运行单元测试时,该元素存在,但未显示出来。我不能在未调用项目的焦点的情况下进行文本输入,这让我认为该项目已显示。
这是我的 OutlinedTextField:
@Composable
fun ChangeUserNameInput(
userName: String,
onChangeUserName: (String) -> Unit
) {
Box(modifier = Modifier.testTag(UpdateUserNameTags.USERNAME).alpha(1f)) {
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.alpha(1f)
.semantics { contentDescription = UpdateUserNameTags.USERNAME },
value = userName,
onValueChange = onChangeUserName,
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent,
focusedIndicatorColor = MaterialTheme.colors.primary,
unfocusedIndicatorColor = niro,
disabledIndicatorColor = Color.Transparent,
focusedLabelColor = MaterialTheme.colors.primary,
unfocusedLabelColor = niro,
textColor = MaterialTheme.colors.onBackground
),
label = {
Text(text = stringResource(id = R.string.update_user_name))
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text
)
)
}
}
这是我的测试:
@Test
fun `测试用户名输入文本是否显示`() = runTest {
val value = composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME)
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).assertExists()
composeTestRule.awaitIdle()
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).assertIsDisplayed() // 在这里失败
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).performTextInput(" Welsh")
value.assertTextEquals("Kristy Welsh")
//composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).assertTextContains("Kristy Welsh")
}
我无法弄清楚为什么该项目没有显示出来。
英文:
I have an OutlinedTextField that I'm testing in unit tests. When I run the app, the TextField is always displayed. However, when I run the unit tests, the element exists, but is not displayed. I can't do text input without calling focus on the item, which I am assuming means the item is displayed.
Here is my OutlinedTextField:
@Composable
fun ChangeUserNameInput(
userName: String,
onChangeUserName: (String) -> Unit) {
Box(modifier = Modifier.testTag(UpdateUserNameTags.USERNAME).alpha(1f)) {
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.alpha(1f)
.semantics { contentDescription = UpdateUserNameTags.USERNAME },
value = userName,
onValueChange = onChangeUserName,
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.Transparent,
focusedIndicatorColor = MaterialTheme.colors.primary,
unfocusedIndicatorColor = niro,
disabledIndicatorColor = Color.Transparent,
focusedLabelColor = MaterialTheme.colors.primary,
unfocusedLabelColor = niro,
textColor = MaterialTheme.colors.onBackground
),
label = {
Text(text = stringResource(id = R.string.update_user_name))
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text
)
)
}
}
Here is my test:
@Test
fun `test to see if username typed text is Displayed`() = runTest {
val value = composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME)
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).assertExists()
composeTestRule.awaitIdle()
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).assertIsDisplayed() ---> FAILS here
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).performTextInput(" Welsh")
value.assertTextEquals("Kristy Welsh")
//composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).assertTextContains("Kristy Welsh")
}
I can't figure out why the item is not displaying.
答案1
得分: 0
I've translated the code portion for you:
我已经测试过这个,并通过在测试函数的开头设置内容来使其工作。
composeTestRule.setContent { ChangeUserNameInput("Kristy", {}) }
看起来你正在测试传递给文本框的状态是否在输入文本时更新 - 这意味着你的设置内容函数需要包括保存传递给ChangeUserNameInput()的用户名状态的组合项。
这是我使用的测试类。
@RunWith(AndroidJUnit4::class)
class StackTest {
@get:Rule
val composeTestRule = createComposeRule()
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun teststack() = runTest {
composeTestRule.setContent { ChangeUserNameInput("Kristy", {}) }
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).assertExists()
composeTestRule.awaitIdle()
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).assertIsDisplayed() // 在这里失败
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).performTextInput(" Welsh")
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).printToLog("OutlineTextBox Test")
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).assertTextEquals(R.string.update_user_name, "Kristy Welsh")
}
}
最后注意,assertTextEquals() 测试了你的OutlinedTextField中的标签 + 值,所以你需要在assertTextEquals()中添加标签文本,就像我在这个函数中所做的那样。
Please note that I've translated the code portion only, as per your request.
英文:
I've tested this out and got it working by setting the content at the start of your test function.
composeTestRule.setContent { ChangeUserNameInput("Kristy",{})}
It looks like you're testing the state passed to the text box is updated when you enter text - this means your set content function will need to include the composable that is holding the state of username passed to ChangeUserNameInput().
Here is the test class I used.
@RunWith(AndroidJUnit4::class)
class StackTest {
@get:Rule
val composeTestRule = createComposeRule()
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun teststack() = runTest {
composeTestRule.setContent { ChangeUserNameInput("Kristy",{})}
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).assertExists()
composeTestRule.awaitIdle()
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).assertIsDisplayed() // fails here
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).performTextInput(" Welsh")
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).printToLog("OutlineTextBox Test")
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).assertTextEquals(R.string.update_user_name, "Kristy Welsh")
}
}
Final note, assertTextEquals() tests the label + value in your OutlinedTextField so you need to add the label text to your assertTextEquals() as i've done in this function.
答案2
得分: 0
My problem actually was that the screen was too large and a bunch of the content was off screen.
I solved it by making the screen scrollable and then doing performScrollTo
:
@Test
fun test to see if username is showing
() = runTest {
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).assertExists()
composeTestRule.onNodeWithTag("Annotated String").assertIsDisplayed()
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).performScrollTo()
composeTestRule.onNodeWithTag(UPDATE_USER_SCREEN).assertIsDisplayed()
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).assertTextContains("Kristy")
}
英文:
My problem actually was that the screen was too large and a bunch of the content was off screen.
I solved it by making the screen scrollable and the doing performScrollTo:
@Test
fun `test to see if username is showing`() = runTest {
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).assertExists()
composeTestRule.onNodeWithTag("Annotated String").assertIsDisplayed()
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).performScrollTo()
composeTestRule.onNodeWithTag(UPDATE_USER_SCREEN).assertIsDisplayed()
composeTestRule.onNodeWithTag(UpdateUserNameTags.USERNAME).onChildAt(0).assertTextContains("Kristy")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论