Hey! :wave: I’m trying to implement integration t...
# compose
n
Hey! 👋 I’m trying to implement integration tests in my app. These tests use the app as it is, and run from the entry point, so I’m creating a
composeTestRule
from the Main Activity. I’m using Nav Component in the app and the navigation is working when launched as an app, but it doesn’t when launched as an Android test. I was so surprised that I created a really simple project reproducing the error and it’s indeed happening there. Here’s the project: https://github.com/iruizmar/nav-component-ui-test-reproducer As you can see, the
MainActivity
just waits for 1s and then navigates to “screen”. The test is waiting forever. If the app is launched normally, the navigation happens but it doesn’t happen in the test. What am I missing? Thanks!
@Ian Lake I could really use your help here 🙏 . Sorry for the direct ping. This is driving me crazy.
c
The repo seems to be private.
1
gratitude thank you 1
s
If you do not run the entire app but do a little snippet only with NavHost without anything else do you experience the same? Maybe if you just copy a test from in there directly? https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:navigati[…]idx/navigation/compose/NavHostTest.kt;l=103-125?q=NavHostTest
n
I'll try that asap!
c
I guess your issue is the “Main Dispatcher” you set. you should better use the
mainClock
from the compose rule. https://developer.android.com/reference/kotlin/androidx/compose/ui/test/MainTestClock
n
Ah, first time I heard about that 🥲
Advancing the main clock did make the difference. Thanks, Christian. But I’m surprised, should the tests be advancing the time manually all the time?
s
The tests from up here seem to use
runOnIdle
and
runOnUiThread
is that something you can also try?
n
Those functions are really syntax sugar, thanks for pointing towards them. But they don’t make the clock advance, they just ensure that the code inside is run on Idle. To make it work, this is needed:
Copy code
@Test
    fun test() = runTest {
        composeTestRule.awaitIdle()
        composeTestRule.runOnIdle {
            assert(true)
        }
    }
It’s not that much, but it requires a bit of knowledge of how the Compose code was written. For instance, you could do something like:
Copy code
runTest {
   composeTestRule.awaitIdle()
   composeTestRule.runOnIdle { 
   //We are sure this is run on idle, 
   // but it's on the main thread, so you can't assert with `onNode***`
}
but, as you can see, you should advance the clock manually. Something even cooler is:
Copy code
fun test() = runTest {      composeTestRule.waitUntilExactlyOneExists(hasText("screen"))       composeTestRule.onNodeWithText("screen").performClick()
    }
Anyway, this has helped me a lot. Thanks guys! 🫶