Android ofrece una variedad de herramientas y APIs que pueden ayudarte a crear pruebas para diferentes tamaños de pantalla y ventana.
Anular configuración de dispositivo
El elemento DeviceConfigurationOverride
componible te permite anular
atributos de configuración para probar varios tamaños de pantalla y ventana en Compose
y diseños. La anulación ForcedSize
se ajusta a cualquier diseño en el espacio disponible.
que te permite ejecutar cualquier
Prueba de IU en cualquier tamaño de pantalla. Por ejemplo, puedes usar un factor de forma de teléfono pequeño.
para ejecutar todas tus pruebas de IU, incluidas las pruebas de IU para teléfonos grandes, plegables y
tablets.
DeviceConfigurationOverride(
DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp))
) {
MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping.
}
Además, puedes usar este elemento componible para configurar la escala de fuentes, los temas y otras que tal vez quieras probar en diferentes tamaños de ventana.
Robolectric
Usa Robolectric para ejecutar pruebas de IU basadas en vistas o Compose en la JVM de forma local: no se requieren dispositivos ni emuladores. Puedes configurar Robolectric para usar tamaños de pantalla específicos, entre otras propiedades útiles
En el siguiente ejemplo de Now in Android, Robolectric está configurado Para emular un tamaño de pantalla de 1,000 x 1,000 dp con una resolución de 480 dpi, haz lo siguiente:
@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 { ... }
También puedes establecer los calificadores del cuerpo de la prueba, como se hace en este fragmento de El ejemplo de Now in Android:
val (width, height, dpi) = ...
// Set qualifiers from specs.
RuntimeEnvironment.setQualifiers("w${width}dp-h${height}dp-${dpi}dpi")
Ten en cuenta que RuntimeEnvironment.setQualifiers()
actualiza el sistema y
los recursos de la aplicación con la configuración nueva, pero no activa ninguna acción
en actividades activas u otros componentes.
Puede obtener más información en la documentación de Configuración del dispositivo de Robolectric.
Dispositivos administrados por Gradle
El complemento de Android para Gradle dispositivos administrados por Gradle (GMD) te permite definir las especificaciones de los emuladores y dispositivos reales en los que se ejecutan las pruebas instrumentadas. Crear especificaciones para dispositivos con diferentes tamaños de pantalla para implementar una estrategia de prueba en la que ciertas pruebas ejecutarse en ciertos tamaños de pantalla. Usando GMD con integración continua (CI), puedes asegurarte de que se ejecuten las pruebas adecuadas cuando sea necesario aprovisionar e iniciar emuladores y simplificar la configuración de la 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"
}
}
}
}
}
Puedes encontrar varios ejemplos de GMD en el proyecto testing-samples.
Firebase Test Lab
Usa Firebase Test Lab (FTL), o un servicio de granja de dispositivos similar, para ejecutar tu en dispositivos reales específicos a los que quizá no tengas acceso, como plegables o tablets de diferentes tamaños. Firebase Test Lab es una plataforma paga servicio con un nivel gratuito. FTL también admite la ejecución de pruebas en emuladores. Estos servicios mejoran la confiabilidad y velocidad de las pruebas de instrumentación, ya que puede aprovisionar dispositivos y emuladores con anticipación.
Para obtener información sobre el uso de FTL con GMD, consulta Escala tus pruebas con Dispositivos administrados por Gradle.
Cómo filtrar pruebas con el ejecutor de pruebas
Una estrategia de prueba óptima no debería verificar lo mismo dos veces, por lo que la mayoría No es necesario que las pruebas de IU se ejecuten en varios dispositivos. Por lo general, debes filtrar la IU ejecutando todas o la mayoría de ellas en un factor de forma de teléfono y solo un subconjunto dispositivos con diferentes tamaños de pantalla.
Puedes anotar ciertas pruebas para que se ejecuten solo con ciertos dispositivos y, luego, pasarlas un argumento a AndroidJUnitRunner con el comando que ejecuta la y pruebas.
Por ejemplo, puedes crear diferentes anotaciones:
annotation class TestExpandedWidth
annotation class TestCompactWidth
Úsalas en diferentes pruebas:
class MyTestClass {
@Test
@TestExpandedWidth
fun myExample_worksOnTablet() {
...
}
@Test
@TestCompactWidth
fun myExample_worksOnPortraitPhone() {
...
}
}
Luego, puedes usar android.testInstrumentationRunnerArguments.annotation
cuando ejecutes las pruebas para filtrar determinadas. Por ejemplo, si estás
con dispositivos administrados por Gradle:
$ ./gradlew pixelTabletApi30DebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation='com.sample.TestExpandedWidth'
Si no usas GMD y administras emuladores en CI, primero asegúrate de que el emulador o dispositivo correcto esté listo y conectado y, luego, pasa el parámetro a uno de los comandos de Gradle para ejecutar pruebas de instrumentación:
$ ./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.annotation='com.sample.TestExpandedWidth'
Ten en cuenta que el dispositivo Espresso (consulta la siguiente sección) también puede filtrar pruebas usando propiedades del dispositivo.
Dispositivo Espresso
Usa Espresso Device para realizar acciones en emuladores durante pruebas con cualquiera tipo de pruebas instrumentadas, incluidas las pruebas Espresso, Compose o UI Automator. Estas acciones pueden incluir configurar el tamaño de la pantalla o activar o desactivar los estados plegables. o posturas clave. Por ejemplo, puedes controlar un emulador de dispositivos plegables y configurarlos en modo de mesa. El dispositivo Espresso también contiene reglas JUnit y anotaciones para requieren ciertas funciones:
@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()))
}
}
Ten en cuenta que el dispositivo Espresso aún se encuentra en la etapa alfa y tiene lo siguiente: requisitos:
- Complemento de Android para Gradle 8.3 o una versión posterior
- Android Emulator 33.1.10 o una versión posterior
- Dispositivo virtual Android que ejecute el nivel de API 24 o uno posterior
Pruebas de filtro
Espresso puede leer las propiedades de los dispositivos conectados para permitirte pruebas de filtro con anotaciones. Si no se cumplen los requisitos anotados, se omiten las pruebas.
Anotación RequiresDeviceMode
La anotación RequiresDeviceMode
se puede usar varias veces para indicar
una prueba que se ejecutará solo si se admiten todos los valores de DeviceMode
en el dispositivo.
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()))
}
}
Anotación RequiresDisplay
La anotación RequiresDisplay
te permite especificar el ancho y la altura de
la pantalla del dispositivo con clases de tamaño, que definen buckets de dimensiones.
siguiendo las clases de tamaño de ventana oficiales.
class OnDeviceTest {
...
@Test
@RequiresDisplay(EXPANDED, COMPACT)
fun myScreen_expandedWidthCompactHeight() {
...
}
}
Cambia el tamaño de las pantallas
Usa el método setDisplaySize()
para cambiar el tamaño de las dimensiones de la pantalla.
durante el tiempo de ejecución. Usa el método junto con DisplaySizeRule
.
, que garantiza que los cambios realizados durante las pruebas se deshagan antes de la
próxima prueba.
@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.
}
}
Cuando cambias el tamaño de una pantalla con setDisplaySize()
, no se modifica la densidad
del dispositivo. Si una dimensión no cabe en el dispositivo de destino, la
falla con un UnsupportedDeviceOperationException
. Para evitar que las pruebas
que se ejecuten en este caso, usa la anotación RequiresDisplay
para filtrarlos:
@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.
}
}
Prueba de restauración del estado
La clase StateRestorationTester
se usa para probar el restablecimiento del estado.
para componentes componibles sin volver a crear actividades. Esto agiliza las pruebas
y más confiable, ya que la recreación de actividades es un proceso complejo con varias
mecanismos de sincronización:
@Test
fun compactDevice_selectedEmailEmailRetained_afterConfigChange() {
val stateRestorationTester = StateRestorationTester(composeTestRule)
// Set content through the StateRestorationTester object.
stateRestorationTester.setContent {
MyApp()
}
// Simulate a config change.
stateRestorationTester.emulateSavedInstanceStateRestore()
}
Biblioteca de Window Testing
La biblioteca de Window Testing contiene utilidades para ayudarte a escribir pruebas que se basen en activar o verificar funciones relacionadas con la administración de ventanas, como la actividad o atributos plegables. El artefacto está disponible a través de la Repositorio de Maven.
Por ejemplo, puedes usar la función FoldingFeature()
para generar un
FoldingFeature
personalizado, que puedes usar en vistas previas de Compose. En Java,
Usa la función createFoldingFeature()
.
En una vista previa de Compose, puedes implementar FoldingFeature
de la siguiente manera:
@Preview(showBackground = true, widthDp = 480, heightDp = 480)
@Composable private fun FoldablePreview() =
MyApplicationTheme {
ExampleScreen(
displayFeatures = listOf(FoldingFeature(Rect(0, 240, 480, 240)))
)
}
Además, puedes emular las funciones de pantalla en las pruebas de IU con el
función TestWindowLayoutInfo()
.
En el siguiente ejemplo, se simula un FoldingFeature
con una
HALF_OPENED
bisagra vertical en el centro de la pantalla y comprueba si
el diseño sea el esperado:
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()
}
}
Objetos 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()))
}
}
Puedes encontrar más muestras en el proyecto WindowManager.
Recursos adicionales
Documentación
- Lineamientos de calidad de las apps en pantallas grandes
- Cómo probar apps en Android
- Cómo probar tu diseño de Compose
Ejemplos
- Ejemplo de WindowManager
- Muestras de dispositivos Espresso
- Ahora en Android
- Utiliza pruebas de captura de pantalla para verificar diferentes tamaños de pantalla.
Codelabs