오늘은 Jetpack Navigation의 Test Code 작성하는 법에 대해 알아 보겠습니다!
우선 테스트 코드 작성을 위해 아래 의존성을 추가해 줍니다.
dependencies {
implementation("androidx.navigation:navigation-compose:$nav_version")
androidTestImplementation("androidx.compose.ui:ui-test-junit4:$junit_version")
}
테스트 코드 작성
시작하기 앞서 해당 테스트는 안드로이드 기기에서 실행되어야 하므로 /app/src/androidTest 폴더 안에 위치해 있어야 합니다.
우선 이해하기 쉽게 아래 두 화면과 NavHost가 정의되어 있다고 가정하겠습니다.
sealed class Screen(val route: String) {
object ScreenA : Screen("ScreenA")
object ScreenB : Screen("ScreenB")
}
@Composable
fun TestNavHost(navController: NavHostController) {
NavHost(navController, startDestination = Screen.ScreenA.route) {
composable(Screen.ScreenA.route) { /* ... */ }
composable(Screen.ScreenB.route) { /* ... */ }
}
}
간단하게 A 화면에서 B 화면으로 이동하는 테스트 코드는 아래와 같이 작성하실 수 있습니다.
class NavigationTest {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun screenA_navigateButtonClicked_navigateToscreenB() {
composeTestRule.setContent {
val navController = rememberNavController()
TestNavHost(navController = navController)
}
// ScreenA에서 ScreenB로 네비게이션하는 버튼을 찾아 클릭
composeTestRule.onNodeWithContentDescription("Navigate to ScreenB").performClick()
// ScreenB에 도달했는지 확인
composeTestRule.onNodeWithContentDescription("ScreenB Content").assertIsDisplayed()
}
}
createComposeRule()
을 사용하여 테스트 환경을 초기화 하고,
onNodeWithContentDescription()
을 통해 UI 요소를 찾아 조작할 수 있습니다.
위에서 사용된 메소드의 역할은 아래와 같습니다.
createComposeRule()
- 해당 메소드는 Compose UI 테스트를 위한 테스트 환경을 설정하고
Compose의 컴포넌트를 테스트하기 전에 필요한 초기화와 정리 작업을 제공합니다. - @get:Rule 어노테이션과 함께 사용되며 setContent 메소드를 사용하여 Compose 컴포넌트를 로드 합니다.
performClick()
- 해당 메소드는 Compose에서 UI 요소에 클릭 이벤트를 시뮬레이션하는 데 사용됩니다.
- 테스트하고자 하는 Compose 요소를 onNodeWithContentDescription, onNodeWithText 등의 함수로 찾은 후,
performClick 함수를 적용해 해당 요소에 가상의 클릭 이벤트를 발생시킵니다.
assertIsDisplayed()
- 해당 메소드는 특정 UI 요소가 화면에 표시되는지 여부를 검증하는 데 사용됩니다.
- 테스트하고자 하는 Compose 요소를 onNodeWithContentDescription, onNodeWithText 등의 함수로 찾은 후
assertIsDisplayed를 호출하여 해당 요소가 사용자에게 보이는지 확인합니다.
이 함수는 요소가 화면에 표시되지 않으면 테스트 실패를 반환합니다.
다른 방법으로 navigation 테스트
위의 방법 말고도 navController.currentBackStackEntry?.destination?.route
방식으로 테스트 하는 방법 예시입니다.
currentBackStackEntry를 사용하여 현재 문자열 경로를 예상 경로와 비교함으로써 검증하실 수 있습니다.
class NavigationTest {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun aScreen_navigateButtonClicked_navigateToBScreen() {
composeTestRule.setContent {
val navController = rememberNavController()
TestNavHost(navController = navController)
}
composeTestRule.onNodeWithContentDescription("Navigate to ScreenB")
.performClick()
val route = navController.currentBackStackEntry?.destination?.route
assertEquals(route, "ScreenB")
}
}
navController.navigate 직접 호출하는 방법
해당 방법은 UI 스레드에서 navController.navigate()를 호출해야 하므로,
메인 스레드 디스패처와 함께 코루틴을 사용하여 이를 수행할 수 있습니다.
class NavigationTest {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun aScreen_navigateButtonClicked_navigateToBScreen() {
runBlocking {
withContext(Dispatchers.Main) {
navController.navigate(Screen.ScreenB.route)
}
}
composeTestRule
.onNodeWithContentDescription("ScreenB Content")
.assertIsDisplayed()
}
}
새로운 상태에 대한 Assertion을 만들기 전에 호출이 발생해야 하므로, runBlocking 호출로 래핑 해주시면 됩니다.
'Android' 카테고리의 다른 글
Android - CustomView (1) | 2024.01.03 |
---|---|
Android - Image Preloading Trouble Shooting (1) | 2023.12.30 |
Android - JUnit 단위 테스트 (0) | 2023.07.04 |
Android - GitHub에 API Key, Hash 값 숨기기 (0) | 2023.01.05 |
안드로이드 - csv 파일 읽기 (0) | 2022.11.21 |