Study Record

[Android] Compose 단위 테스트 본문

안드로이드/compose

[Android] Compose 단위 테스트

초코초코초코 2023. 9. 13. 16:30
728x90

😶 단위 테스트 전략

좋은 테스트 전략의 핵심은 코드의 여러 경로와 경계를 포괄하는 것이다. 아주 기본적인 수준에서 테스트는 성공 경로, 오류 경로, 경계 사례라는 세가지 시나리오로 분류할 수 있다.

 

성공 경로(행복한 경로 테스트)

긍정적인 흐름의 기능 테스트에 집중하는 테스트로 긍정적인 흐름은 예외나 오류 조건이 없는 흐름이다. 오류 경로 및 경계 시나리오에 비해 성공 경로 시나리오는 앱의 의도된 동작에 초점을 맞추기 때문에 전체 목옥을 만들기 쉽다.

 

오류 경로

부정적인 흐름의 기능 테스트, 즉 앱이 오류 조건 또는 잘못된 사용자 입력에 어떻게 응답하는지 확인하는 데 초점을 맞춘다. 의도된 동작이 실행되지 않을 때 발생할 수 있는 결과가 많기 때문에 가능한 오류 흐름을 모두 파악하기란 매우 어렵다.

 

경계 사례

앱의 경계 조건을 테스트하는 데 초점을 맞춘다.

 

 

😶 좋은 단위 테스트의 일반적인 4가지 특성

 

집중

코드 조각과 같은 단위를 테스트하는 데 중점을 두어야 한다. 이 코드 조각은 대부분 클래스 또는 메서드로 테스트의 범위를 좁히고 동시에 여러 코드가 아닌, 개별 코드의 정확성을 검증하는 데 집중해야 한다.

 

이해 가능

코드를 일을 때 간단하고 이해하기 쉬워야 한다. 개발자는 테스트의 의도를 한눈에 파악할 수 있어야 한다.

 

확장성

일관되게 통과하거나 실패해야 한다. 테스트는 코드를 수정하지 않았는데도 어떤 때는 실패하고 어떤 때는 통과하는 것처럼 불안정해선 안된다.

 

독립형

사람이 상호작용하거나 설정할 필요가 없으며 개별적으로 실행된다.

 

 

😶 의존성 추가

 

 주로 JUnit 프레임워크를 사용하여 단위 테스트를 작성한다.

dependencies {
    implementation platform('androidx.compose:compose-bom:2023.04.00')
    /*
    ...
    */

    androidTestImplementation(platform("androidx.compose:compose-bom:2023.06.01"))
    androidTestImplementation("androidx.compose.ui:ui-test-junit4")

    testImplementation("junit:junit:4.13.2")
}

 

😶 메소드 소개

import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertTrue

// 매개변수1과 매개변수2가 같은지 확인한다.
assertEquals(MAX_NO_OF_WORDS, currentWordCount)

// 매개변수1과 매개변수2가 다른지 확인한다.
assertNotEquals(unScrambledWord, currentScrambledWord)

// 매개변수가 true 인지 확인한다.
assertTrue(currentGameUiState.isGameOver)

// 매개변수가 false 인지 확인한다.
assertFalse(gameUiState.isGuessedWordWrong)

 

 

😶 예시

다음은 테스트 메소드를 사용하는 예시이다. 다음 예시에서는 viewModel 인스턴스가 모든 테스트에서 재사용된다. 그러면 gameViewModel_CorrectWordGuessed_ScoreUpdatedAndErrorFlagUnset() 테스트가 실행 된 후, viewModel 이 업데이트 된 상태로 gameViewModel_IncorrectGuess_ErrorFlagSet() 테스트를 실행하는 것이냐고 물으면 그렇지 않다.

class GameViewModelTest {
    private val viewModel = GameViewModel()

    @Test
    fun gameViewModel_CorrectWordGuessed_ScoreUpdatedAndErrorFlagUnset() {
        var currentGameUiState = viewModel.uiState.value
        val correctPlayerWord = getUnscrambledWord(currentGameUiState.currentScrambledWord)

        viewModel.updateUserGuess(correctPlayerWord)
        viewModel.checkUserGuess()

        currentGameUiState = viewModel.uiState.value

        assertFalse(currentGameUiState.isGuessedWordWrong)
        assertEquals(SCORE_AFTER_FIRST_CORRECT_ANSWER, currentGameUiState.score)
    }

    @Test
    fun gameViewModel_IncorrectGuess_ErrorFlagSet() {
        val incorrectPlayerWord = "and"

        viewModel.updateUserGuess(incorrectPlayerWord)
        viewModel.checkUserGuess()

        val currentGameUiState = viewModel.uiState.value

        assertEquals(0, currentGameUiState.score)
        assertTrue(currentGameUiState.isGuessedWordWrong)
    }

테스트 메서드는 개별적으로 실행되어 변경 가능한 테스트 인스턴스 상태로 인한 예상치 못한 부작용을 방지한다. 기본적으로 JUnit4 부터 각 테스트 메서드가 실행되기 전 테스트 클래스의 새 인스턴스를 만든다. 

 

 

 

https://developer.android.com/training/testing/fundamentals?hl=ko#benefits 

 

테스트 기본 요소  |  Android 개발자  |  Android Developers

테스트 기본 요소 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 사용자는 버튼을 누르는 것부터 기기에 정보를 다운로드하는 것에 이르기까지 다양한 수

developer.android.com

 

 

728x90

'안드로이드 > compose' 카테고리의 다른 글

[Android] Compose 화면 간 이동(Navigation)  (0) 2023.09.19
[Android] Compose 다이얼로그  (0) 2023.09.13
[Android] Compose ViewModel  (0) 2023.09.13
[Android] Compose 애니메이션 효과  (0) 2023.09.06
[Android] Compose Appbar  (0) 2023.09.04