다양한 화면 크기를 테스트하는 라이브러리 및 도구

Android는 이 API에 관한 테스트를 만드는 데 도움이 되는 다양한 도구와 API를 다양한 화면과 창 크기가 있습니다.

DeviceConfigurationOverride

의 반주자

DeviceConfigurationOverride 컴포저블을 사용하면 Compose에서 여러 화면 및 창 크기를 테스트하는 구성 속성 있습니다. ForcedSize 재정의는 사용 가능한 공간의 모든 레이아웃에 맞습니다. 이 기능을 사용하면 모든 화면 크기에서의 UI 테스트 예를 들어 소형 휴대전화 폼 팩터를 사용할 수 있습니다. 를 사용하여 대형 스마트폰, 폴더블, 있습니다.

   DeviceConfigurationOverride(
        DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp))
    ) {
        MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping.
    }
드림 <ph type="x-smartling-placeholder">
</ph>
그림 1. \*Now in Android*와 같이 더 작은 폼 팩터 기기 내에 태블릿 레이아웃을 맞추기 위해 DeviceConfigurationOverride를 사용합니다.

또한 이 컴포저블을 사용하여 글꼴 크기, 테마 등을 설정할 수 있습니다. 여러 창 크기에서 테스트할 수 있습니다.

Robolectric

Robolectric을 사용하여 JVM에서 Compose 또는 뷰 기반 UI 테스트 실행 로컬에서: 기기나 에뮬레이터가 필요하지 않습니다. 특정 IP 주소를 구성하여 Robolectric - 다른 유용한 속성 중에서 특정 화면 크기를 사용합니다.

Now in Android의 다음 에서는 Robolectric이 구성됩니다. 480dpi 해상도로 1000x1000dp 화면 크기를 에뮬레이트합니다.

@RunWith(RobolectricTestRunner::class)
// Configure Robolectric to use a very large screen size that can fit all of the test sizes.
// This allows enough room to render the content under test without clipping or scaling.
@Config(qualifiers = "w1000dp-h1000dp-480dpi")
class NiaAppScreenSizesScreenshotTests { ... }

이 스니펫에서와 같이 테스트 본문에서 한정자를 설정할 수도 있습니다. Now in Android 예:

val (width, height, dpi) = ...

// Set qualifiers from specs.
RuntimeEnvironment.setQualifiers("w${width}dp-h${height}dp-${dpi}dpi")

RuntimeEnvironment.setQualifiers()는 시스템을 업데이트하고 애플리케이션 리소스에 새 구성이 있지만 작업을 트리거하지 않음 기타 구성 요소에 대해 자세히 파악할 수 있습니다.

자세한 내용은 Robolectric 기기 구성 문서를 참고하세요.

Gradle 관리 기기

Gradle 관리 기기 (GMD) Android Gradle 플러그인 이를 통해 에뮬레이터 및 실제 기기의 사양을 계측 테스트가 실행됩니다. 다음이 있는 기기 사양 만들기 다양한 화면 크기를 이용해 테스트 전략을 구현할 수 있습니다. 특정 화면 크기에서 실행되도록 할 수 있습니다 지속적 통합과 함께 GMD 사용 (CI)에서는 필요한 경우 적절한 테스트가 실행되는지 확인할 수 있습니다. 에뮬레이터를 프로비저닝 및 실행하고 CI 설정을 간소화할 수 있습니다.

android {
    testOptions {
        managedDevices {
            devices {
                // Run with ./gradlew nexusOneApi30DebugAndroidTest.
                nexusOneApi30(com.android.build.api.dsl.ManagedVirtualDevice) {
                    device = "Nexus One"
                    apiLevel = 30
                    // Use the AOSP ATD image for better emulator performance
                    systemImageSource = "aosp-atd"
                }
                // Run with ./gradlew  foldApi34DebugAndroidTest.
                foldApi34(com.android.build.api.dsl.ManagedVirtualDevice) {
                    device = "Pixel Fold"
                    apiLevel = 34
                    systemImageSource = "aosp-atd"
                }
            }
        }
    }
}

testing-samples 프로젝트에서 여러 GMD의 예를 확인할 수 있습니다.

Firebase Test Lab

Firebase Test Lab (FTL) 또는 유사한 기기 팜 서비스를 사용하여 액세스할 수 없는 특정 실제 기기에서 다양한 크기의 폴더블 또는 태블릿 Firebase Test Lab은 무료 서비스를 제공합니다. FTL은 에뮬레이터에서의 테스트 실행도 지원합니다. 이러한 서비스는 다음과 같은 이유로 계측 테스트의 안정성과 속도를 개선합니다. 기기와 에뮬레이터를 미리 프로비저닝할 수 있습니다.

GMD에서 FTL을 사용하는 방법에 대한 자세한 내용은 다음을 참조하세요. 테스트 확장: Gradle 관리 기기를 참조하세요.

테스트 실행기를 사용한 테스트 필터링

최적의 테스트 전략은 동일한 것을 두 번 확인하는 것은 아니기 때문에 대부분의 테스트에서 UI 테스트는 여러 기기에서 실행할 필요가 없습니다. 일반적으로 UI를 필터링하여 전체 또는 대부분을 휴대전화 폼 팩터에서 실행하고 여러 기기에서 사용할 수 있습니다.

특정 기기에서만 실행되도록 특정 테스트에 주석을 달고 AndroidJUnitRunner에 인수를 있습니다

예를 들어 다음과 같이 다양한 주석을 만들 수 있습니다.

annotation class TestExpandedWidth
annotation class TestCompactWidth

다양한 테스트에서 사용하세요.

class MyTestClass {

    @Test
    @TestExpandedWidth
    fun myExample_worksOnTablet() {
        ...
    }

    @Test
    @TestCompactWidth
    fun myExample_worksOnPortraitPhone() {
        ...
    }

}

그런 다음 android.testInstrumentationRunnerArguments.annotation를 사용하면 됩니다. 속성을 사용하여 특정 테스트를 필터링할 수 있습니다. 예를 들어 Gradle 관리 기기를 사용하는 경우

$ ./gradlew pixelTabletApi30DebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation='com.sample.TestExpandedWidth'

GMD를 사용하지 않고 CI에서 에뮬레이터를 관리하는 경우 먼저 올바른 에뮬레이터나 기기가 준비되고 연결된 다음 이 매개변수를 Gradle 명령어 중 하나에 추가하여 계측 테스트를 실행합니다.

$ ./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation='com.sample.TestExpandedWidth'

Espresso Device (다음 섹션 참조)는 기기 속성

Espresso 기기

Espresso Device를 사용하여, 테스트에서 에뮬레이터에 관한 작업을 Espresso, Compose 또는 UI Automator 테스트를 비롯한 계측 테스트 유형 이러한 작업에는 화면 크기 설정 또는 폴더블 상태 전환이 포함될 수 있습니다. 상태를 나타냅니다 예를 들어 폴더블 에뮬레이터를 제어하고 다음과 같이 설정할 수 있습니다. 탁자 모드 또한 Espresso Device에는 JUnit 규칙과 주석도 포함되어 있습니다. 특정 기능이 필요합니다.

@RunWith(AndroidJUnit4::class)
class OnDeviceTest {

    @get:Rule(order=1) val activityScenarioRule = activityScenarioRule<MainActivity>()

    @get:Rule(order=2) val screenOrientationRule: ScreenOrientationRule =
        ScreenOrientationRule(ScreenOrientation.PORTRAIT)

    @Test
    fun tabletopMode_playerIsDisplayed() {
        // Set the device to tabletop mode.
        onDevice().setTabletopMode()
        onView(withId(R.id.player)).check(matches(isDisplayed()))
    }
}

Espresso Device는 아직 알파 단계이며 다음을 포함합니다. 요구사항:

  • Android Gradle 플러그인 8.3 이상
  • Android Emulator 33.1.10 이상
  • API 수준 24 이상을 실행하는 Android Virtual Device

테스트 필터링

Espresso Device는 연결된 기기의 속성을 읽어 주석을 사용하여 테스트를 필터링합니다. 주석이 달린 요구사항이 충족되지 않으면 테스트를 건너뜁니다.

RequiresDeviceMode 주석

RequiresDeviceMode 주석을 여러 번 사용하여 모든 DeviceMode 값이 지원되는 경우에만 실행되는 테스트 할 수 있습니다.

class OnDeviceTest {
    ...
    @Test
    @RequiresDeviceMode(TABLETOP)
    @RequiresDeviceMode(BOOK)
    fun tabletopMode_playerIdDisplayed() {
        // Set the device to tabletop mode.
        onDevice().setTabletopMode()
        onView(withId(R.id.player)).check(matches(isDisplayed()))
    }
}

RequiresDisplay 주석

RequiresDisplay 주석을 사용하면 요소의 너비와 높이를 지정할 수 있습니다. 크기 버킷을 정의하는 크기 클래스를 사용하는 기기 화면 이는 공식 창 크기 클래스를 따릅니다.

class OnDeviceTest {
    ...
    @Test
    @RequiresDisplay(EXPANDED, COMPACT)
    fun myScreen_expandedWidthCompactHeight() {
        ...
    }
}

디스플레이 크기 조절

setDisplaySize() 메서드를 사용하여 화면 크기를 조정합니다. 런타임 시 사용할 수 있습니다. 이 메서드를 DisplaySizeRule와 함께 사용합니다. 클래스가 실행되기 전에 테스트 중에 변경한 내용이 실행취소되어 있습니다.

@RunWith(AndroidJUnit4::class)
class ResizeDisplayTest {

    @get:Rule(order = 1) val activityScenarioRule = activityScenarioRule<MainActivity>()

    // Test rule for restoring device to its starting display size when a test case finishes.
    @get:Rule(order = 2) val displaySizeRule: DisplaySizeRule = DisplaySizeRule()

    @Test
    fun resizeWindow_compact() {
        onDevice().setDisplaySize(
            widthSizeClass = WidthSizeClass.COMPACT,
            heightSizeClass = HeightSizeClass.COMPACT
        )
        // Verify visual attributes or state restoration.
    }
}

setDisplaySize()로 디스플레이 크기를 조절해도 밀도에는 영향을 미치지 않습니다. 따라서 크기가 대상 기기에 맞지 않으면 테스트는 UnsupportedDeviceOperationException와 함께 실패합니다. 테스트를 여기서는 RequiresDisplay 주석을 사용하여 필터링합니다.

@RunWith(AndroidJUnit4::class)
class ResizeDisplayTest {

    @get:Rule(order = 1) var activityScenarioRule = activityScenarioRule<MainActivity>()

    // Test rule for restoring device to its starting display size when a test case finishes.
    @get:Rule(order = 2) var displaySizeRule: DisplaySizeRule = DisplaySizeRule()

    /**
     * Setting the display size to EXPANDED would fail in small devices, so the [RequiresDisplay]
     * annotation prevents this test from being run on devices outside the EXPANDED buckets.
     */
    @RequiresDisplay(
        widthSizeClass = WidthSizeClassEnum.EXPANDED,
        heightSizeClass = HeightSizeClassEnum.EXPANDED
    )
    @Test
    fun resizeWindow_expanded() {
        onDevice().setDisplaySize(
            widthSizeClass = WidthSizeClass.EXPANDED,
            heightSizeClass = HeightSizeClass.EXPANDED
        )
        // Verify visual attributes or state restoration.
    }
}

StateRestorationTester입니다.

StateRestorationTester 클래스는 상태 복원을 테스트하는 데 사용됩니다. 할 수 있습니다. 이렇게 하면 테스트가 더 빨라집니다. 더 안정적이며, 이는 활동 재생성이 여러 작업이 필요한 복잡한 프로세스이기 때문입니다. 동기화 메커니즘:

@Test
fun compactDevice_selectedEmailEmailRetained_afterConfigChange() {
    val stateRestorationTester = StateRestorationTester(composeTestRule)

    // Set content through the StateRestorationTester object.
    stateRestorationTester.setContent {
        MyApp()
    }

    // Simulate a config change.
    stateRestorationTester.emulateSavedInstanceStateRestore()
}

창 테스트 라이브러리

윈도우 테스트 라이브러리에는 윈도우와 리눅스 OS'에 의존하는 테스트를 작성하는 데 도움이 되는 유틸리티가 창 관리와 관련된 기능(예: 활동)을 활성화하거나 확인합니다. 임베딩 또는 폴더블 기능이 있습니다. 아티팩트는 Google의 Maven 저장소를 사용합니다.

예를 들어 FoldingFeature() 함수를 사용하여 맞춤 FoldingFeature을 사용합니다. 이는 Compose 미리보기에서 사용할 수 있습니다. Java에서 createFoldingFeature() 함수를 사용합니다.

Compose 미리보기에서는 다음과 같은 방식으로 FoldingFeature를 구현할 수 있습니다.

@Preview(showBackground = true, widthDp = 480, heightDp = 480)
@Composable private fun FoldablePreview() =
    MyApplicationTheme {
        ExampleScreen(
            displayFeatures = listOf(FoldingFeature(Rect(0, 240, 480, 240)))
        )
 }

또한 다음을 사용하여 UI 테스트에서 디스플레이 기능을 에뮬레이션할 수 있습니다. TestWindowLayoutInfo() 함수 다음 예는 다음과 같이 FoldingFeature를 시뮬레이션합니다. HALF_OPENED 설치한 다음, 화면 중앙에서 수직 힌지를 레이아웃은 예상되는 것입니다.

Compose

import androidx.window.layout.FoldingFeature.Orientation.Companion.VERTICAL
import androidx.window.layout.FoldingFeature.State.Companion.HALF_OPENED
import androidx.window.testing.layout.FoldingFeature
import androidx.window.testing.layout.TestWindowLayoutInfo
import androidx.window.testing.layout.WindowLayoutInfoPublisherRule

@RunWith(AndroidJUnit4::class)
class MediaControlsFoldingFeatureTest {

    @get:Rule(order=1)
    val composeTestRule = createAndroidComposeRule<ComponentActivity>()

    @get:Rule(order=2)
    val windowLayoutInfoPublisherRule = WindowLayoutInfoPublisherRule()

    @Test
    fun foldedWithHinge_foldableUiDisplayed() {
        composeTestRule.setContent {
            MediaPlayerScreen()
        }

        val hinge = FoldingFeature(
            activity = composeTestRule.activity,
            state = HALF_OPENED,
            orientation = VERTICAL,
            size = 2
        )

        val expected = TestWindowLayoutInfo(listOf(hinge))
        windowLayoutInfoPublisherRule.overrideWindowLayoutInfo(expected)

        composeTestRule.waitForIdle()

        // Verify that the folding feature is detected and media controls shown.
        composeTestRule.onNodeWithTag("MEDIA_CONTROLS").assertExists()
    }
}

import androidx.window.layout.FoldingFeature.Orientation
import androidx.window.layout.FoldingFeature.State
import androidx.window.testing.layout.FoldingFeature
import androidx.window.testing.layout.TestWindowLayoutInfo
import androidx.window.testing.layout.WindowLayoutInfoPublisherRule

@RunWith(AndroidJUnit4::class)
class MediaControlsFoldingFeatureTest {

    @get:Rule(order=1)
    val activityRule = ActivityScenarioRule(MediaPlayerActivity::class.java)

    @get:Rule(order=2)
    val windowLayoutInfoPublisherRule = WindowLayoutInfoPublisherRule()

    @Test
    fun foldedWithHinge_foldableUiDisplayed() {
        activityRule.scenario.onActivity { activity ->
            val feature = FoldingFeature(
                activity = activity,
                state = State.HALF_OPENED,
                orientation = Orientation.VERTICAL)
            val expected = TestWindowLayoutInfo(listOf(feature))
            windowLayoutInfoPublisherRule.overrideWindowLayoutInfo(expected)
        }

        // Verify that the folding feature is detected and media controls shown.
        onView(withId(R.id.media_controls)).check(matches(isDisplayed()))
    }
}

WindowManager 프로젝트에서 더 많은 샘플을 확인할 수 있습니다.

추가 리소스

문서

샘플

Codelab