팡세영
Log sey
팡세영
전체 방문자
오늘
어제
  • 분류 전체보기 (74) N
    • PS (45)
      • programmers (13)
      • 백준 (29)
    • Android (16)
    • Daily (0)
    • Kotlin (6)
    • Design Pattern (2) N
    • Java (1)
    • Flutter (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • binding
  • 정렬
  • 백준
  • 안드로이드
  • CustomView
  • compose
  • BFS
  • 자바
  • 문자열
  • 프로그래머스
  • flutter
  • programmers
  • ArcitecturePattern
  • 구현
  • TestCode
  • mvvm
  • LEVEL2
  • 코틀린
  • 이분탐색
  • programmers #프로그래머스
  • Kotlin
  • java
  • 완전탐색
  • DFS
  • Android
  • 의존성 주입
  • 하단네비게이션바
  • 골드
  • 해쉬맵
  • 실버

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
팡세영

Log sey

Android

안드로이드 - Jetpack Compose Navigation Test Code

2023. 12. 30. 10:25

오늘은 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
    'Android' 카테고리의 다른 글
    • Android - CustomView
    • Android - Image Preloading Trouble Shooting
    • Android - JUnit 단위 테스트
    • Android - GitHub에 API Key, Hash 값 숨기기
    팡세영
    팡세영
    Android, CS, PS

    티스토리툴바