[Android] jetpack compose 테스트 코드 실전편!

윤호이·2023년 11월 1일
0

Test

목록 보기
3/13
post-thumbnail

지난 이야기

[Android] Jetpack Compose 테스트코드 어떻게 짜는거예요?

서론

지난번에는 간단하게 compose상 UI 테스트 코드를 어떻게 짜는지
맛을 봤습니다.
이번엔 제가 만든 앱을 바탕으로 테스트 코드를 짜는 과정을
포스트 하도록 하겠습니다.

UI분석

이 앱은 제가 파일 탐색기에대해 조사하는겸 간단하게 만든 샘플 앱입니다.

이 앱의 UI를 테스트 해보기로 합시다!

상태

파일리스트

버튼

Column(
        Modifier
            .fillMaxSize()
            .background(Color.White)
    ) {
        val modifier = Modifier.weight(1f)
        StatusView(
            Modifier,
            isMultiple,
            viewModel.uploadProgress.collectAsState(),
            viewModel.uploadSize.collectAsState(),
            viewModel.uploaded.collectAsState()
        )
        FileListView(viewModel.fileList, modifier, viewModel.fileIndex.collectAsState())
        ButtonMenuView(
            { viewModel.changeState(it) },
            isSending,
            { viewModel.sendFile(context.contentResolver) },
            { viewModel.cancel() },
            { viewModel.showInfo() },
            { viewModel.deleteFileList() },
            navHostController
        )
    }

화면을 굉장히 직관적으로 나눠봤습니다.
Column 안에 View를 3개 쫘라락~ 한게 끝입니다.
UI 컴포넌트별로 테스트를 짜면 딱이겠죠?

상태뷰 테스트


    private val safViewModel = SAFViewModel()
    
    @Test
    fun `파일_선택_옵션을_클릭_한다`() {
        composeRule.onNodeWithTag("file_option").assertExists()
        composeRule.onNodeWithTag("file_option").performClick()
        composeRule.onNodeWithTag("file_option").assertIsOn()
    }

    @Test
    fun `텍스트가_표시_되는지_확인_한다`() {
        composeRule.onNodeWithText("Selected Files").assertExists()
        composeRule.onNodeWithText("uploadProgress : ${safViewModel.uploadProgress.value} %")
            .assertExists()
        composeRule.onNodeWithText("uploadSize : ${safViewModel.uploadSize.value} / ${safViewModel.uploaded.value} byte")
            .assertExists()
        composeRule.onNodeWithText("파일 다중 선택").assertExists()

    }
  • 상태창의 파일 다중선택 옵션 체크가 동작하는지 확인한다.
  • 텍스트가 잘 표시 되는지 확인한다.

이 두가지를 테스트 하도록했습니다.

파일리스트뷰 테스트

    @Test
    fun `파일리스트가_비어_있어야_한다`(){
        composeRule.onNodeWithTag("empty").assertIsDisplayed()
    }

    @Test
    fun `파일리스트에_파일을_넣는다`(){
        composeRule.onNodeWithTag("empty").assertIsDisplayed()
        safViewModel.fileList.add(dummyItem1)
        composeRule.onNodeWithTag("file_list").assertIsDisplayed()
        composeRule.onNodeWithTag("file_name",useUnmergedTree = true).assertIsDisplayed()
    }

    @Test
    fun `파일을_클릭하면_삭제된다`(){
        safViewModel.fileList.add(dummyItem1)
        composeRule.onNodeWithTag("file_item").assertIsDisplayed()
        composeRule.onNodeWithTag("file_item").performClick()
        composeRule.onNodeWithTag("empty").assertIsDisplayed()
    }

    @Test
    fun `파일리스트를_스크롤한다`(){
        repeat(5){
            safViewModel.fileList.add(dummyItem1)
        }
        safViewModel.fileList.add(dummyItem2)
        composeRule.onNodeWithTag("file_list").assertExists()
        composeRule.onNodeWithTag("file_list").performScrollToIndex(4)
        composeRule.onNodeWithText(Util.extractLastPathComponent(dummyItem2.displayName)).assertIsDisplayed()
    }
  • 파일리스트에 아이템이 없으면 empty가 표시되는 것을 확인한다.
  • 파일리스트에 파일을 넣으면 empty 가 사라지고 파일아이템이 표시되는 것을 확인한다.
  • 파일아이템을 클릭하면 파일이 지워지고 파일리스트에 empty가 나오는 것을 확인한다.
  • 파일리스트를 스크롤 하여 아이템이 정상 표시되는지 확인한다.

버튼뷰 테스트

    @Test
    fun `버튼이_표시되는지_확인한다`() {
        composeRule.onNodeWithText("파일 선택").assertIsDisplayed()
        composeRule.onNodeWithText("전체 삭제").assertIsDisplayed()
        composeRule.onNodeWithText("폴더 전체 선택").assertIsDisplayed()
        composeRule.onNodeWithTag("button_view").performScrollToNode(hasText("로그 보기"))
        composeRule.onNodeWithText("파일 보내기").assertIsDisplayed()
        composeRule.onNodeWithText("로그 보기").assertIsDisplayed()
    }

    @Test
    fun `파일보내기_버튼을_누른다`() {
        composeRule.onNodeWithText("파일 보내기").performClick()
        composeRule.onNodeWithText("취소").assertIsDisplayed()
    }

    @Test
    fun `전체_삭제_버튼을_누른다`() {
        safViewModel.fileList.add(dummyItem1)
        composeRule.onNodeWithText(
            Util.extractLastPathComponent(safViewModel.fileList[0].displayName),
            useUnmergedTree = true
        ).assertIsDisplayed()
        composeRule.onNodeWithText("전체 삭제").performClick()
        composeRule.onNodeWithTag("empty").assertIsDisplayed()
    }
  • 버튼이 다보이는지 스크롤 해서 확인한다.
  • 파일 보내기 버튼을 누르면 취소 버튼이 나오는지 확인한다.
  • 전체 삭제 버튼을 누르면 파일 리스트가 비워지고 파일 리스트에 empty가 표시되는지
    확인한다.

하고 싶은 말

지난번에 이어 compose 테스트 코드에 대해 다뤄봤습니다.
테스트 코드를 읽어 보셨으면 느끼셨을텐데
테스트 케이스 써둔걸 그대로 코드로 옮긴 것 뿐입니다.
compose는 테스트 코드 짜는 방식이 굉장히 직관적이어서
짜기 편합니다.

이 글을 읽으신 독자 분들도 자신이 짠 UI를 한번 테스트 해보세요!
조금만 짜보면 바로 이해갑니다.

공부 하실 때 compose test cheatsheet를 꼭 보세요!!!

참조 & 전체 코드

https://github.com/lyh990517/saftest
https://developer.android.com/jetpack/compose/testing-cheatsheet?hl=ko

profile
열정은 내 삶의 방식, 꾸준함은 내 삶의 증명

0개의 댓글