Android menyediakan berbagai alat dan API yang dapat membantu Anda membuat pengujian untuk berbagai ukuran layar dan jendela.
DeviceConfigurationOverride
Composable DeviceConfigurationOverride
memungkinkan Anda mengganti
atribut konfigurasi untuk menguji beberapa ukuran layar dan jendela dalam tata letak
Compose. Penggantian ForcedSize
cocok dengan tata letak apa pun di ruang yang tersedia,
yang memungkinkan Anda menjalankan
pengujian UI apa pun pada semua ukuran layar. Misalnya, Anda dapat menggunakan faktor bentuk ponsel kecil
untuk menjalankan semua pengujian UI, termasuk pengujian UI untuk ponsel besar, perangkat foldable, dan
tablet.
DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp))
) {
MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping.
}
Selain itu, Anda dapat menggunakan composable ini untuk menetapkan skala font, tema, dan properti lainnya yang mungkin ingin Anda uji pada berbagai ukuran jendela.
Robolectric
Gunakan Robolectric untuk menjalankan pengujian Compose atau UI berbasis tampilan di JVM secara lokal—tidak perlu perangkat atau emulator. Anda dapat mengonfigurasi Robolectric untuk menggunakan ukuran layar tertentu, di antara properti berguna lainnya.
Dalam contoh berikut dari Now in Android, Robolectric dikonfigurasi untuk mengemulasikan ukuran layar 1000x1000 dp dengan resolusi 480 dpi:
@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 { ... }
Anda juga dapat menetapkan penentu dari isi pengujian seperti yang dilakukan dalam cuplikan ini dari contoh Now in Android:
val (width, height, dpi) = ...
// Set qualifiers from specs.
RuntimeEnvironment.setQualifiers("w${width}dp-h${height}dp-${dpi}dpi")
Perhatikan bahwa RuntimeEnvironment.setQualifiers()
akan mengupdate resource sistem dan
aplikasi dengan konfigurasi baru, tetapi tidak memicu tindakan apa pun
pada aktivitas aktif atau komponen lainnya.
Anda dapat membaca selengkapnya di dokumentasi Konfigurasi Perangkat Robolectric.
Perangkat yang dikelola Gradle
Plugin Android Gradle perangkat yang dikelola Gradle (GMD) memungkinkan Anda menentukan spesifikasi emulator dan perangkat sungguhan tempat pengujian berinstrumen Anda berjalan. Buat spesifikasi untuk perangkat dengan berbagai ukuran layar untuk menerapkan strategi pengujian dengan pengujian tertentu harus dijalankan pada ukuran layar tertentu. Dengan menggunakan GMD dengan Continuous Integration (CI), Anda dapat memastikan bahwa pengujian yang sesuai berjalan saat diperlukan, menyediakan dan meluncurkan emulator, serta menyederhanakan penyiapan 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"
}
}
}
}
}
Anda dapat menemukan beberapa contoh GMD di project testing-samples.
Firebase Test Lab
Gunakan Firebase Test Lab (FTL), atau layanan pertanian perangkat yang serupa, untuk menjalankan pengujian pada perangkat nyata tertentu yang mungkin tidak dapat Anda akses, seperti perangkat foldable atau tablet dengan berbagai ukuran. Firebase Test Lab adalah layanan berbayar dengan paket gratis. FTL juga mendukung pengujian yang berjalan di emulator. Layanan ini meningkatkan keandalan dan kecepatan pengujian berinstrumen karena dapat menyediakan perangkat dan emulator terlebih dahulu.
Untuk informasi tentang penggunaan FTL dengan GMD, lihat Menskalakan pengujian dengan perangkat yang dikelola Gradle.
Menguji pemfilteran dengan runner pengujian
Strategi pengujian yang optimal tidak boleh memverifikasi hal yang sama dua kali, sehingga sebagian besar pengujian UI Anda tidak perlu dijalankan di beberapa perangkat. Biasanya, Anda memfilter pengujian UI dengan menjalankan semua atau sebagian besar pengujian pada faktor bentuk ponsel dan hanya sebagian pada perangkat dengan ukuran layar yang berbeda.
Anda dapat menganotasi pengujian tertentu agar hanya dijalankan dengan perangkat tertentu, lalu meneruskan argumen ke AndroidJUnitRunner menggunakan perintah yang menjalankan pengujian.
Misalnya, Anda dapat membuat anotasi yang berbeda:
annotation class TestExpandedWidth
annotation class TestCompactWidth
Dan gunakan pada pengujian yang berbeda:
class MyTestClass {
@Test
@TestExpandedWidth
fun myExample_worksOnTablet() {
...
}
@Test
@TestCompactWidth
fun myExample_worksOnPortraitPhone() {
...
}
}
Kemudian, Anda dapat menggunakan properti android.testInstrumentationRunnerArguments.annotation
saat menjalankan pengujian untuk memfilter pengujian tertentu. Misalnya, jika Anda
menggunakan perangkat yang dikelola Gradle:
$ ./gradlew pixelTabletApi30DebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation='com.sample.TestExpandedWidth'
Jika Anda tidak menggunakan GMD dan mengelola emulator di CI, pastikan terlebih dahulu bahwa emulator atau perangkat yang benar sudah siap dan terhubung, lalu teruskan parameter ke salah satu perintah Gradle untuk menjalankan pengujian berinstrumen:
$ ./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation='com.sample.TestExpandedWidth'
Perhatikan bahwa Perangkat Espresso (lihat bagian berikutnya) juga dapat memfilter pengujian menggunakan properti perangkat.
Perangkat Espresso
Gunakan Perangkat Espresso untuk melakukan tindakan pada emulator dalam pengujian menggunakan jenis pengujian berinstrumen apa pun, termasuk pengujian Espresso, Compose, atau UI Automator. Tindakan ini dapat mencakup menyetel ukuran layar atau mengubah status atau postur perangkat foldable. Misalnya, Anda dapat mengontrol emulator foldable dan menyetelnya ke mode di atas meja. Perangkat Espresso juga berisi aturan dan anotasi JUnit untuk memerlukan fitur tertentu:
@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()))
}
}
Perhatikan bahwa Perangkat Espresso masih dalam tahap alfa dan memiliki persyaratan berikut:
- Plugin Android Gradle 8.3 atau yang lebih tinggi
- Android Emulator 33.1.10 atau yang lebih tinggi
- Perangkat virtual Android yang menjalankan API level 24 atau yang lebih tinggi
Memfilter pengujian
Perangkat Espresso dapat membaca properti perangkat yang terhubung agar Anda dapat memfilter pengujian menggunakan anotasi. Jika persyaratan yang dianotasi tidak terpenuhi, pengujian akan dilewati.
AnotasiRequiredDeviceMode
Anotasi RequiresDeviceMode
dapat digunakan beberapa kali untuk menunjukkan
pengujian yang hanya akan berjalan jika semua nilai DeviceMode
didukung
di perangkat.
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()))
}
}
Anotasi PrepareDisplay
Anotasi RequiresDisplay
memungkinkan Anda menentukan lebar dan tinggi
layar perangkat menggunakan class ukuran, yang menentukan bucket dimensi
mengikuti class ukuran jendela resmi.
class OnDeviceTest {
...
@Test
@RequiresDisplay(EXPANDED, COMPACT)
fun myScreen_expandedWidthCompactHeight() {
...
}
}
Mengubah ukuran layar
Gunakan metode setDisplaySize()
untuk mengubah ukuran dimensi layar
saat runtime. Gunakan metode ini bersama dengan class DisplaySizeRule
, yang memastikan bahwa setiap perubahan yang dilakukan selama pengujian diurungkan sebelum
pengujian berikutnya.
@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.
}
}
Saat mengubah ukuran layar dengan setDisplaySize()
, Anda tidak akan memengaruhi kepadatan
perangkat, sehingga jika dimensi tidak sesuai dengan perangkat target, pengujian
akan gagal dengan UnsupportedDeviceOperationException
. Untuk mencegah pengujian
berjalan dalam hal ini, gunakan anotasi RequiresDisplay
untuk memfilternya:
@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
Class StateRestorationTester
digunakan untuk menguji pemulihan status
untuk komponen composable tanpa membuat ulang aktivitas. Hal ini membuat pengujian lebih cepat
dan lebih andal, karena pembuatan ulang aktivitas adalah proses yang kompleks dengan beberapa
mekanisme sinkronisasi:
@Test
fun compactDevice_selectedEmailEmailRetained_afterConfigChange() {
val stateRestorationTester = StateRestorationTester(composeTestRule)
// Set content through the StateRestorationTester object.
stateRestorationTester.setContent {
MyApp()
}
// Simulate a config change.
stateRestorationTester.emulateSavedInstanceStateRestore()
}
Library Pengujian Jendela
Library Pengujian Jendela berisi utilitas untuk membantu Anda menulis pengujian yang mengandalkan atau memverifikasi fitur yang terkait dengan pengelolaan jendela, seperti penyematan aktivitas atau fitur perangkat foldable. Artefak tersedia melalui Repositori Maven Google.
Misalnya, Anda dapat menggunakan fungsi FoldingFeature()
untuk membuat
FoldingFeature
kustom, yang dapat Anda gunakan di pratinjau Compose. Di Java,
gunakan fungsi createFoldingFeature()
.
Dalam pratinjau Compose, Anda dapat menerapkan FoldingFeature
dengan cara berikut:
@Preview(showBackground = true, widthDp = 480, heightDp = 480)
@Composable private fun FoldablePreview() =
MyApplicationTheme {
ExampleScreen(
displayFeatures = listOf(FoldingFeature(Rect(0, 240, 480, 240)))
)
}
Selain itu, Anda juga dapat mengemulasi fitur tampilan dalam pengujian UI menggunakan
fungsi TestWindowLayoutInfo()
.
Contoh berikut menyimulasikan FoldingFeature
dengan engsel vertikal
HALF_OPENED
di tengah layar, lalu memeriksa apakah
tata letak sesuai dengan yang diharapkan:
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()
}
}
View
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()))
}
}
Anda dapat menemukan contoh lainnya di project WindowManager.
Referensi lainnya
Dokumentasi
- Pedoman kualitas aplikasi perangkat layar besar
- Menguji aplikasi di Android
- Menguji tata letak Compose
Contoh
- Contoh WindowManager
- Contoh Perangkat Espresso
- Kini di Android
- Menggunakan pengujian screenshot untuk memverifikasi berbagai ukuran layar
Codelab