Instrumentation Testing: Testing individual composables - devrath/RunTracer GitHub Wiki
Testing individual composables
- Instrumentation testing for individual composables in Jetpack Compose provides a robust framework for ensuring UI correctness, improving code quality, facilitating refactoring, and enhancing the user experience.
- By automating these tests, you can save time, reduce manual effort, and maintain a high standard of reliability and performance in your Android applications.
Dependencies
dependencies {
// For Android Instrumentation tests
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
// For Compose testing
androidTestImplementation 'androidx.compose.ui:ui-test-junit4:1.0.0'
debugImplementation 'androidx.compose.ui:ui-test-manifest:1.0.0'
}
Approach
- We shall use two classes one for test and another as robot.
- Thus we shall use the
ROBOT PATTERN
.
Code
TestClass
class RegisterScreenKtTest {
@get:Rule
val composeRule = createComposeRule()
private val robot = RegisterScreenRobot(composeRule)
@Test
fun testRegisterScreen_whetherInitialUiIsLoadedProperly() {
robot.apply {
loadRegisterScreen()
validateUiLoaded()
}
}
@Test
fun testRegisterScreen_inputIsValidEmailEntered() {
robot.apply {
loadRegisterScreen()
inputValidEmail()
validateEnteredEmail()
}
}
@Test
fun testRegisterScreen_inputIsValidPasswordEntered() {
robot.apply {
loadRegisterScreen()
inputValidPassword()
validateEnteredPassword()
}
}
}
RobotClass
internal class RegisterScreenRobot(private val composeRule: ComposeContentTestRule) {
private val context = InstrumentationRegistry.getInstrumentation().context
private val createAccountText = context.getString(R.string.create_account)
private val atLeastOneNumber = context.getString(R.string.at_least_one_number)
private val containsLowerCharacter = context.getString(R.string.contains_lowercase_char)
private val containsUpperCharacter = context.getString(R.string.contains_uppercase_char)
private val registerText = context.getString(R.string.register)
private val emailText = context.getString(R.string.email)
private val passwordText = context.getString(R.string.password)
val emailInput = "[email protected]"
val passwordInput = "Test@123"
/**
* Loading and setting the register screen
*/
fun loadRegisterScreen() {
composeRule.setContent {
RunTracerTheme {
RegisterScreen(
state = RegisterState(
passwordValidationState = PasswordValidationState(
hasNumber = true
)
),
onAction = {}
)
}
}
}
/**
* Check if all the UI elements are properly loaded
*/
fun validateUiLoaded() {
composeRule.apply {
onNodeWithText(createAccountText).assertIsDisplayed()
onNodeWithText(atLeastOneNumber).assertIsDisplayed()
onNodeWithText(containsLowerCharacter).assertIsDisplayed()
onNodeWithText(containsUpperCharacter).assertIsDisplayed()
onNodeWithText(registerText).assertIsDisplayed()
}
}
/**
* ********************* Adding inputs *********************
*/
fun inputValidEmail() {
composeRule.onNodeWithTag(emailText).assertExists()
composeRule
.onNodeWithTag(emailText)
.performTextInput(emailInput)
}
fun inputValidPassword() {
composeRule.onNodeWithTag(passwordText).assertExists()
composeRule
.onNodeWithTag(passwordText)
.performTextInput(passwordInput)
}
/**
* ********************* Adding inputs *********************
*/
/**
* ********************* Validating inputs *********************
*/
fun validateEnteredEmail() {
composeRule.onNodeWithText(emailInput).assertIsDisplayed()
}
fun validateEnteredPassword() {
composeRule.onNodeWithText(passwordText).assertIsDisplayed()
}
/**
* ********************* Validating inputs *********************
*/
}