특정 Composable에 대한 Isolated Test를 위한 createComposeRule
우리는 지금까지 createComposeRule을 사용해 UI 테스트를 진행했다. createComposeRule을 사용하면, 특정한 Composable을 화면에 표시할 수 있고, 해당 UI를 조작해 테스트를 진행할 수 있다.
예를 들어 다음 코드와 같이 CirclePlayButton을 화면에 표시하고, 클릭한 다음, 해당 클릭이 제대로 일어났는지를 테스트할 수 있다.
class OnNodeWithContentDescriptionTest {
@get:Rule
val composeRule = createComposeRule()
@Test
fun testCircleButtonClick() {
// Given
var isClicked = false
composeRule.setContent {
CirclePlayButton(
boxSize = 48.dp,
iconSize = 36.dp
) {
isClicked = true
}
}
// When
composeRule.onNodeWithContentDescription("Circle Play Button").performClick()
// Then
Assert.assertTrue(isClicked)
}
}
이 테스트를 실행한 화면은 다음과 같다.
createComposeRule을 사용했을 때 어떻게 이런 동작이 일어날 수 있을까?
정답은 바로 createComposeRule 함수의 선언부에 있다. createComposeRule은 Compose에서 일반적으로 사용하는 Activity인 ComponentActivity를 시작시키며, 테스트 코드의 composeRule.setContent 함수를 통해 이 ComponentActivity 속에 들어갈 UI를 설정할 수 있는 것이다.
actual fun createComposeRule(): ComposeContentTestRule =
createAndroidComposeRule<ComponentActivity>()
여기서 특정 Activity를 시작시키기 위해 사용되는 것이 바로 createAndroidComposeRule 함수이며, 이 createAndroidComposeRule 함수를 사용해 ComponentActivity가 아닌 실제 애플리케이션의 Activity도 시작할 수 있다.
createAndroidComposeRule 사용해 실제 앱의 Activity 테스트하기
예를 들어 다음과 같이 작성된 MainActivity가 있다고 해보자.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AndroidUITestCourseTheme {
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.padding(4.dp),
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
item {
EmojiText(modifier = Modifier, emoji = "👍", content = "Good")
}
item {
EmojiText(modifier = Modifier, emoji = "🙏", content = "Pray")
}
item {
CirclePlayButton(
boxSize = 48.dp,
iconSize = 36.dp,
onClick = {
}
)
}
}
}
}
}
}
}
이 MainActivity는 Emoji와 Text가 함께 들어간 EmojiText 컴포저블과 Play 버튼을 Lazy Column을 통해 화면에 표시해 다음과 같은 화면을 표시한다.
이 Activity를 테스트하기 위해서 우리는 createAndroidComposeRule<MainActivity>() 를 사용할 수 있으며, 모든 EmojiText 컴포저블이 화면에 표시되는지 확인하는 테스트는 다음과 같이 만들 수 있다.
class AndroidComposeRuleTest {
@get:Rule
val composeRule = createAndroidComposeRule<MainActivity>()
@Test
fun assertAllEmojiTextDisplayed() {
// Then
composeRule.onNodeWithText("Good").assertIsDisplayed()
composeRule.onNodeWithText("Pray").assertIsDisplayed()
}
}
createAndroidComposeRule을 사용해 특정 Activity에 대한 테스트를 작성하면, 이미 화면이 구성되어 있기 때문에 composeRule.setContent를 사용하지 않으며, 화면상의 UI Node와의 인터렉션과 단언만을 실행하면 되는 것을 볼 수 있다. 아래 영상은 위 테스트를 실행해 본 결과이다.
*UI 테스트는 워낙 빨리 끝나기 때문에 중간에 Thread.sleep을 두었다. 실제 테스트에서는 쓰면 안된다.
정리
- createComposeRule은 createAndroidComposeRule을 사용해 ComponentActivity를 시작시킨다.
- createAndroidComposeRule을 사용해 특정 Activity를 테스트할 수 있다.