Compose 테스트는 기본적으로 UI와 동기화됩니다. ComposeTestRule
로 어설션이나 작업을 호출하면 테스트가 미리 동기화되어 UI 트리가 유휴 상태가 될 때까지 기다립니다.
일반적으로 별도의 조치를 취할 필요가 없습니다. 하지만 몇 가지 극단적 사례에 관해 알아야 합니다.
테스트가 동기화되면 Compose 앱이 가상 클록을 사용하여 시간을 앞당깁니다. 즉 Compose 테스트가 실시간으로 실행되지 않으므로 최대한 빨리 통과할 수 있습니다.
하지만 테스트를 동기화하는 메서드를 사용하지 않는 경우 리컴포지션이 발생하지 않으며 UI가 일시중지된 것으로 표시됩니다.
@Test
fun counterTest() {
val myCounter = mutableStateOf(0) // State that can cause recompositions.
var lastSeenValue = 0 // Used to track recompositions.
composeTestRule.setContent {
Text(myCounter.value.toString())
lastSeenValue = myCounter.value
}
myCounter.value = 1 // The state changes, but there is no recomposition.
// Fails because nothing triggered a recomposition.
assertTrue(lastSeenValue == 1)
// Passes because the assertion triggers recomposition.
composeTestRule.onNodeWithText("1").assertExists()
}
이 요구사항은 앱의 나머지 부분이 아니라 Compose 계층구조에만 적용됩니다.
자동 동기화 사용 중지
assertExists()
와 같은 ComposeTestRule
을 통해 어설션이나 작업을 호출하면 테스트가 Compose UI와 동기화됩니다. 경우에 따라 이 동기화를 중지하고 클록을 직접 제어해야 할 수도 있습니다. 예를 들어 UI가 계속 사용 중일 때 애니메이션의 정확한 스크린샷을 캡처하는 시간을 제어할 수 있습니다. 자동 동기화를 사용 중지하려면 mainClock
의 autoAdvance
속성을 false
로 설정하세요.
composeTestRule.mainClock.autoAdvance = false
일반적으로 그런 다음에 직접 시간을 앞당깁니다. advanceTimeByFrame()
을 사용하여 정확히 한 프레임을 앞당기거나 advanceTimeBy()
를 사용하여 특정 기간만큼 앞당길 수 있습니다.
composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)
유휴 리소스
Compose는 모든 작업과 어설션이 유휴 상태에서 실행되도록 테스트와 UI를 동기화하여 필요에 따라 기다리거나 클록을 앞당길 수 있습니다. 하지만 결과가 UI 상태에 영향을 미치는 일부 비동기 작업은 테스트가 인식하지 못하는 동안 백그라운드에서 실행할 수 있습니다.
테스트 중인 앱이 사용 중인지 유휴 상태인지 결정할 때 고려되도록 이러한 유휴 리소스를 만들고 테스트에 등록합니다. 예를 들어 Espresso 또는 Compose와 동기화되지 않는 백그라운드 작업을 실행하는 경우 추가 유휴 리소스를 등록해야 하지 않으면 조치를 취할 필요가 없습니다.
이 API는 Espresso의 유휴 리소스와 매우 유사하며 테스트 대상이 유휴 상태인지 아니면 사용 중인지 나타냅니다. Compose 테스트 규칙을 사용하여 IdlingResource
구현을 등록합니다.
composeTestRule.registerIdlingResource(idlingResource)
composeTestRule.unregisterIdlingResource(idlingResource)
수동 동기화
경우에 따라 Compose UI를 테스트의 다른 부분 또는 테스트 중인 앱과 동기화해야 합니다.
waitForIdle()
함수는 Compose가 유휴 상태가 될 때까지 기다리지만 이 함수는 autoAdvance
속성에 종속됩니다.
composeTestRule.mainClock.autoAdvance = true // Default
composeTestRule.waitForIdle() // Advances the clock until Compose is idle.
composeTestRule.mainClock.autoAdvance = false
composeTestRule.waitForIdle() // Only waits for idling resources to become idle.
두 경우 모두 waitForIdle()
은 대기 중인 그리기 및 레이아웃 단계도 기다립니다.
또한 advanceTimeUntil()
을 사용하여 특정 조건이 충족될 때까지 클록을 앞당길 수 있습니다.
composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }
지정된 조건은 클록의 영향을 받을 수 있는 상태를 확인해야 합니다(조건은 Compose의 상태만 확인함).
조건 대기
데이터 로드나 Android의 측정 또는 그리기 (즉, Compose 외부의 측정 또는 그리기)와 같은 외부 작업에 종속되는 모든 조건은 waitUntil()
과 같이 더 일반적인 개념을 사용해야 합니다.
composeTestRule.waitUntil(timeoutMs) { condition }
다음과 같은 waitUntil
도우미를 사용할 수도 있습니다.
composeTestRule.waitUntilAtLeastOneExists(matcher, timeoutMs)
composeTestRule.waitUntilDoesNotExist(matcher, timeoutMs)
composeTestRule.waitUntilExactlyOneExists(matcher, timeoutMs)
composeTestRule.waitUntilNodeCount(matcher, count, timeoutMs)
추가 리소스
- Android에서 앱 테스트: 기본 Android 테스트 방문 페이지에서는 테스트 기본사항과 기법을 더 폭넓게 살펴볼 수 있습니다.
- 테스트의 기본사항: Android 앱 테스트의 핵심 개념을 자세히 알아봅니다.
- 로컬 테스트: 자체 워크스테이션에서 로컬로 일부 테스트를 실행할 수 있습니다.
- 계측 테스트: 계측 테스트도 실행하는 것이 좋습니다. 즉, 기기에서 직접 실행되는 테스트입니다.
- 지속적 통합: 지속적 통합을 사용하면 테스트를 배포 파이프라인에 통합할 수 있습니다.
- 다양한 화면 크기 테스트: 사용자가 사용할 수 있는 기기가 많으므로 다양한 화면 크기를 테스트해야 합니다.
- Espresso: 뷰 기반 UI를 위한 것이지만 Espresso 지식은 여전히 Compose 테스트의 일부 측면에 유용할 수 있습니다.