top of page
Matt

효율적인 안드로이드 UI 테스팅: 의존성 주입 프레임워크 없는 기능적 기술

서론

제 다른 블로그 게시글에서 논의했듯이, 프로젝트를 위한 좋고 깔끔한 자동화된 테스트를 작성하는 것의 중요성은 과장될 수 없습니다. 이 게시글에서는 기능적 접근 방식을 사용하여 안드로이드 테스트를 작성하는 방법을 보여드리겠습니다. 부작용이 있는 함수를 주입하여 다양한 시나리오를 용이하게 하고, 의존성 주입(DI) 프레임워크가 필요 없이 이를 수행하는 방법을 설명하겠습니다. 이 프레임워크는 종종 불필요한 보일러플레이트와 복잡성을 추가합니다.


앱 테스팅 구조화하기

함수형 프로그래밍에서는 클래스와 달리 함수가 일급 구성요소입니다. 앱을 효과적으로 테스트하기 위해, 우리는 함수를 주입해야 합니다. 이를 통해 앱의 모든 다양한 행동을 커버하는 테스트를 작성할 수 있습니다. 예를 들어, 하루의 뉴스 피드를 표시하는 간단한 앱을 고려해보세요. 우리는 다음과 같은 행동에 대한 다양한 테스트를 작성할 수 있습니다:

  • 뉴스가 없는 경우 친근한 메시지 표시

  • 뉴스 헤드라인을 올바르게 표시

  • 뉴스를 가져오는 데 오류가 있는 경우 친근한 오류 메시지 표시


이를 위해, Either<Error, Response>를 반환하는 getNewsF 함수를 가질 수 있습니다. 우리는 이 함수를 우리 앱 코드에 주입해야 합니다. 그래서 테스트에서 이 함수가 호출될 때 그 행동을 제어할 수 있으며, 위에 개요를 설명한 테스트를 효과적으로 작성할 수 있습니다.


그건 그렇고, Either 타입은 함수형 타입이며 arrow core에서 나온 것입니다: https://arrow-kt.io/


AppF 및 AppFProvider:

우리 앱에는 주입하고 싶은 여러 함수가 일반적으로 포함되어 있습니다. 먼저, AppF라는 클래스를 만듭시다. 이것은 우리의 함수를 포함하는 간단한 데이터 클래스입니다:

data class AppF(
    val getNewsF: () -> Either<Error, Response>
)

AppF를 주입하는 진입점은 AppFProvider라는 싱글톤 클래스에서 AppF 인스턴스에 접근하는 지연 설정자입니다:

object AppFProvider {
    var appF: AppF = AppF()
}

그리고 나서 이것이 MainActivity에 주입됩니다:

class MainActivity : ComponentActivity() {
    private val appF: AppF by lazy { AppFProvider.appF }
    ...
}

기본적으로, AppFProvider는 REAL 인스턴스로 설정되며, 테스트에서는 필요한 어떠한 구현으로도 변경할 수 있습니다. 테스트 내에서 시나리오를 수동으로 만들어 활성화를 제어해야 합니다. 테스트를 마치면 시나리오를 닫습니다. 이것이 우리가 하는 방법입니다:

fun init(appF: AppF = buildTestAppF()): ActivityScenario<MainActivity> {
    AppFProvider.appF = appF

    return ActivityScenario.launch(MainActivity::class.java)
}

예시 getNews 테스트:

@Test
fun testIfGettingNewsErrorsThenErrorIsDisplayedAndLogged() {
    val expectedError = Error("Oh dear! failed to get news")
    val loggedErrors = mutableListOf<Error>()
    val logError = { error: Error ->
        loggedErrors.add(error)
        Unit
    }
    init(
        AppF(
            getNewsF = { expectedError.left() }
        )
    ).use {
        loggedErrors.shouldHaveSize(1)
        loggedErrors[0].shouldBe(expectedError)

        onView(withText("Failed to get news. Please try again later"))
            .check(matches(isDisplayed()))
    }
}

지원 방법

이 콘텐츠는 항상 무료로 유지될 것이며, 가치 있다고 생각되면 다른 사람들과 공유하는 것을 고려해 주세요. 또한, 우리 게임을 다운로드하고 솔직한 리뷰를 남기는 것이 큰 지원이 됩니다. 질문이나 피드백이 있으면 언제든지 연락주세요. 최선을 다해 응답하겠습니다.


오늘 애플 앱 스토어에서 Falling Sky를 다운로드하세요: https://apps.apple.com/app/id6446787964


X에서 저희를 팔로우하세요: https://x.com/_kingdomarcade

조회수 1회
bottom of page