Alexandru Gheorghe
Alexandru Gheorghe

Reputation: 371

androidTest fails with Reason: Expected exactly '1' node but found '2' nodes that satisfy: (TestTag = 'Navigation Bottom')

I'm following https://developer.android.com/codelabs/basic-android-kotlin-compose-adaptive-content-for-large-screens?continue=https%3A%2F%2Fdeveloper.android.com%2Fcourses%2Fpathways%2Fandroid-basics-compose-unit-4-pathway-3%23codelab-https%3A%2F%2Fdeveloper.android.com%2Fcodelabs%2Fbasic-android-kotlin-compose-adaptive-content-for-large-screens#4 (code here).

The changes I've applied to the code are the following:

ReplyAppTest.kt

@@ -1,4 +1,30 @@
 package com.example.reply.test
 
+import androidx.activity.ComponentActivity
+import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
+import androidx.compose.ui.test.junit4.createAndroidComposeRule
+import com.example.reply.R
+import com.example.reply.ui.ReplyApp
+import org.junit.Rule
+import org.junit.Test
+
 class ReplyAppTest {
+
+    @get:Rule
+    val composeTestRule = createAndroidComposeRule<ComponentActivity>()
+
+    @Test
+    fun compactDevice_verifyUsingBottomNavigation() {
+        /** Set up compact window */
+        composeTestRule.setContent {
+            ReplyApp(
+                windowSize = WindowWidthSizeClass.Compact
+            )
+        }
+
+        /** Bottom navigation is displayed */
+        composeTestRule.onNodeWithTagForStringId(
+            R.string.navigation_bottom
+        ).assertExists()
+    }
 }

ReplyHomeScreen.kt

                 AnimatedVisibility(
                     visible = navigationType == ReplyNavigationType.BOTTOM_NAVIGATION
                 ) {
@@ -193,6 +205,7 @@ private fun ReplyAppContent(
                         navigationItemContentList = navigationItemContentList,
                         modifier = Modifier
                             .fillMaxWidth()
+                            .testTag(bottomNavigationContentDescription)
                     )
                 }
             }

running the test on Pixel 3a API 30 AVD fails with:

java.lang.AssertionError: Failed: assertExists.
Reason: Expected exactly '1' node but found '2' nodes that satisfy: (TestTag = 'Navigation Bottom')
Nodes found:
1) Node #7 at (l=0.0, t=2000.0, r=1080.0, b=2220.0)px, Tag: 'Navigation Bottom'
IsContainer = 'true'
Has 1 child, 3 siblings
2) Node #39 at (l=0.0, t=2000.0, r=1080.0, b=2220.0)px, Tag: 'Navigation Bottom'
IsContainer = 'true'
Has 1 child, 3 siblings

at androidx.compose.ui.test.SemanticsNodeInteraction.fetchOneOrDie(SemanticsNodeInteraction.kt:145)
at androidx.compose.ui.test.SemanticsNodeInteraction.assertExists(SemanticsNodeInteraction.kt:120)
at androidx.compose.ui.test.SemanticsNodeInteraction.assertExists$default(SemanticsNodeInteraction.kt:119)
at com.example.reply.test.ReplyAppTest.compactDevice_verifyUsingBottomNavigation(ReplyAppTest.kt:28)

as far as I can tell there is only one Composable whose Modifier has .testTag(bottomNavigationContentDescription)

$ find . -type f -iname *.kt | xargs grep -ni --color "navigation_bottom"
./app/src/androidTest/java/com/example/reply/test/ReplyAppTest.kt:27:            R.string.navigation_bottom
./app/src/main/java/com/example/reply/ui/ReplyHomeScreen.kt:201:                        stringResource(R.string.navigation_bottom)

how can the test detect two nodes when I'm only testing for one? what is creating the second one? how can I debug this?

placing a breakpoint in Android Studio on test trigger line(s)

composeTestRule.onNodeWithTagForStringId(
            R.string.navigation_bottom
        ).assertExists()

won't kickstart the debugger

Upvotes: 0

Views: 903

Answers (1)

Alexandru Gheorghe
Alexandru Gheorghe

Reputation: 371

Seems there're two calls to ReplyAppContent in app/src/main/java/com/example/reply/ui/ReplyHomeScreen.kt running at the same time. Commenting the one outside the if condition made the test succeed.

@@ -89,19 +91,17 @@ fun ReplyHomeScreen(
             text = stringResource(id = R.string.tab_spam)
         )
     )
-    ReplyAppContent(
-        navigationType = navigationType,
-        replyUiState = replyUiState,
-        onTabPressed = onTabPressed,
-        onEmailCardPressed = onEmailCardPressed,
-        navigationItemContentList = navigationItemContentList,
-        modifier = modifier
-    )
+//    ReplyAppContent(
+//        navigationType = navigationType,
+//        contentType = contentType,
+//        replyUiState = replyUiState,
+//        onTabPressed = onTabPressed,
+//        onEmailCardPressed = onEmailCardPressed,
+//        navigationItemContentList = navigationItemContentList,
+//        modifier = modifier
+//    )

created: https://github.com/google-developer-training/basic-android-kotlin-compose-training-reply-app/issues/81

Upvotes: 0

Related Questions