1

I m trying to write a UI test using BDD + Compose but I keep getting the following error:

Test not setup properly. Use a ComposeTestRule in your test to be able to interact with composables

I have tried both createComposeRule and createAndroidComposeRule:

@RunWith(AndroidJUnit4::class)
class LoginSteps {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MainActivity>()

    @Given("^I am on the signup page$")
    fun I_am_on_the_signup_page() {
        // the following line produces the error:
        composeTestRule.onNodeWithTag("logo").assertIsDisplayed()
    }

    @When("^I click the login button$")
    fun when_I_click_login() {
        composeTestRule.onNodeWithTag("loginBtn").assertIsDisplayed().performClick()
    }

    @Then("^I should see the login page$")
    fun See_the_Sign_in_page() {
        composeTestRule.onNodeWithTag("LoginWelcomemsg").assertIsDisplayed()
    }
}

Full stacktrace:

java.lang.IllegalStateException: Test not setup properly. Use a ComposeTestRule in your test to be able to interact with composables
    at androidx.compose.ui.test.junit4.ComposeRootRegistry_androidKt.ensureComposeRootRegistryIsSetUp(ComposeRootRegistry.android.kt:254)
    at androidx.compose.ui.test.junit4.ComposeRootRegistry_androidKt.waitForComposeRoots(ComposeRootRegistry.android.kt:261)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.waitForIdle(ComposeUiTest.android.kt:338)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$waitForIdle(ComposeUiTest.android.kt:230)
    at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidTestOwner.getRoots(ComposeUiTest.android.kt:533)
    at androidx.compose.ui.test.TestContext.getAllSemanticsNodes$ui_test_release(TestOwner.kt:86)
    at androidx.compose.ui.test.SemanticsNodeInteraction.fetchSemanticsNodes$ui_test_release(SemanticsNodeInteraction.kt:63)
    at androidx.compose.ui.test.SemanticsNodeInteraction.fetchSemanticsNodes$ui_test_release$default(SemanticsNodeInteraction.kt:56)
    at androidx.compose.ui.test.AndroidAssertions_androidKt.checkIsDisplayed(AndroidAssertions.android.kt:29)
    at androidx.compose.ui.test.AssertionsKt.isDisplayed(Assertions.kt:359)
    at androidx.compose.ui.test.AssertionsKt.assertIsDisplayed(Assertions.kt:33)
    at uk.co.topcashback.topcashback.qa.steps.login.LoginSteps.I_am_on_the_dual_page(LoginSteps.kt:61)
    at ✽.I am on the dual page(file:/features/login.feature:4)

3 Answers 3

0

It appears you're trying to use the test rule from your steps class. Instead, move this to your test class and try that. Test rules belong in the test class.

Sign up to request clarification or add additional context in comments.

1 Comment

Seems a similar answer was provided by someone else here too: stackoverflow.com/a/78347141/465442
0

Try to add an empty compose test rule to you test (or base test) class and pass it to the constructor of your page object class.

For example:

open class TestClass {

    @get:Rule
    val composeTestRule = createEmptyComposeRule()

    private lateinit var loginPage: LoginPageObject

    @Before
    fun setup() {
        loginPage = LoginPageObject(composeTestRule)
    }

    @Test
    fun testLoginProcess() {
        loginPage.assertLogoIsDisplayed()
    }

}

class LoginPageObject(private val composeTestRule: ComposeTestRule) {
    fun assertLogoIsDisplayed() {
        composeTestRule.onNodeWithTag("logo").assertIsDisplayed()
    }
}

Comments

0

The main issue is that @RunWith(AndroidJUnit4::class) should be replaced by @WithJunitRule

The composeTestRule shouldn't be directly instantiated/created at your step classes to support multiple step classes.

The suggested way from https://github.com/cucumber/cucumber-android is to create a separated class for your compose rule. Start with createAndroidComposeRule and switch to createEmptyComposeRule when different app start behaviour is needed.

@WithJunitRule
class ComposeRuleHolder {

    @get:Rule
    val composeRule = createAndroidComposeRule()
}

Then ComposeRuleHolder should be injected into your step classes.

// note: no annotation required here
class LoginSteps(val composeTestRule: ComposeTestRule) { ... }

Cucumber runner does detect when a step class needs some dependencies and will search for a dependency framework. If you don't use any dependency injection framework yet then just add cucumber-picocontainer as android test dependency.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.