Cómo probar las actividades de tu app

Las actividades sirven como contenedores para cada interacción del usuario dentro de tu app, por lo que es importante probar cómo se comportan las actividades de tu app durante los eventos en el nivel del dispositivo, como los siguientes:

  • Otra app, como la app de teléfono del dispositivo, interrumpe la actividad de tu app.
  • El sistema elimina y vuelve a crear tu actividad.
  • El usuario coloca su actividad en un nuevo entorno de ventanas, como pantalla en pantalla (PIP) o el modo multiventana.

En particular, es importante que te asegures de que tu actividad se comporte correctamente en respuesta a los eventos descritos en El ciclo de vida de la actividad.

En esta guía, se describe cómo evaluar la capacidad de tu app para mantener la integridad de los datos y una buena experiencia del usuario mientras las actividades de tu app cambian de estado en sus ciclos de vida.

Cómo probar actividades en Compose

Cuando pruebas una app compilada con Jetpack Compose, por lo general, usas createAndroidComposeRule para iniciar tu actividad e interactuar con tus componentes de la IU.

Sin embargo, para probar eventos en el nivel del dispositivo, como cambios de configuración o la actividad que el sistema coloca en segundo plano o destruye, debes manipular directamente el ciclo de vida de la actividad. Para ello, usas el framework ActivityScenario subyacente.

La regla de prueba de Compose envuelve y administra automáticamente esta situación por ti. A lo largo de esta guía, verás el siguiente patrón que se usa para cerrar la brecha entre las pruebas de IU modernas y la administración estándar del ciclo de vida:

@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()

@Test fun testEvent() {
    val scenario = composeTestRule.activityRule.scenario

    // ...
}

Cómo administrar el estado de una actividad

Un aspecto clave al probar las actividades de tu app es colocarlas en estados particulares. Para definir "esta" parte de tus pruebas, usa instancias de ActivityScenario, que forma parte de la biblioteca Pruebas de AndroidX. Con esta clase, puedes colocar tu actividad en estados que simulan eventos en el nivel del dispositivo.

ActivityScenario es una API multiplataforma que puedes usar tanto en las pruebas de unidades locales como en las pruebas de integración en el dispositivo. En un dispositivo real o virtual, ActivityScenario proporciona seguridad de subprocesos, sincronizando eventos entre el subproceso de instrumentación de tu prueba y el subproceso que ejecuta la actividad que estás probando.

La API es particularmente adecuada para evaluar cómo se comporta una actividad que se está probando cuando se crea o se elimina. En esta sección, se presentan los casos prácticos más comunes asociados con esta API.

Cómo crear una actividad

Para crear la actividad que se está probando, agrega el código que se muestra en el siguiente fragmento:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
       launchActivity<MyActivity>().use {
       }
    }
}

Después de crear la actividad, ActivityScenario la pasa al estado RESUMED. que indica que tu actividad se está ejecutando y es visible para los usuarios. En este estado, puedes interactuar con los elementos componibles de tu actividad con las APIs de prueba de Compose.

Google recomienda que llames a close en la actividad cuando se complete la prueba. De esta manera, se limpian los recursos asociados y se mejora la estabilidad de las pruebas. ActivityScenario implementa Closeable, por lo que puedes aplicar la extensión use para que la actividad se cierre automáticamente.

De manera alternativa, puedes usar createAndroidComposeRule para iniciar automáticamente la Activity antes de cada prueba, controlar la desconexión y otorgarte acceso a los métodos de prueba de la IU de Compose y al ActivityScenario subyacente. En el siguiente ejemplo, se muestra cómo definir una regla y obtener una instancia de una situación de esta:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @Test fun testEvent() {
        val scenario = composeTestRule.activityRule.scenario
    }
}

Cómo pasar la actividad a un nuevo estado

Para pasar la actividad a un estado diferente, como CREATED o STARTED, llama a moveToState. Esta acción simula una situación en la que tu actividad se detiene o se pausa, respectivamente, porque otra app o acción del sistema la interrumpe.

En el siguiente fragmento de código, se muestra un ejemplo del uso de moveToState:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.moveToState(State.CREATED)
        }
    }
}

Cómo determinar el estado actual de la actividad

Para determinar el estado actual de una Activity que se está probando, obtén el valor del campo state dentro de tu objeto ActivityScenario. Es particularmente útil comprobar el estado de una actividad que se está probando si esta redirige a otra actividad o se finaliza a sí misma, como se muestra en el siguiente fragmento de código:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.onActivity { activity ->
              startActivity(Intent(activity, MyOtherActivity::class.java))
            }

            val originalActivityState = scenario.state
        }
    }
}

Cómo volver a crear la actividad

Si un dispositivo tiene pocos recursos, es posible que el sistema elimine una actividad, lo que significa que tu app deberá volver a crearla cuando el usuario regrese a ella. Para simular estas condiciones, llama a recreate:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.recreate()
        }
    }
}

La clase ActivityScenario mantiene el estado de la instancia guardada de la actividad y cualquier objeto con anotaciones mediante @NonConfigurationInstance. Estos objetos se cargan en la nueva instancia de la actividad que estás probando.

Cómo obtener los resultados de la actividad

Para ver el código de resultado o los datos asociados con una actividad finalizada, debes obtener el valor del campo result dentro de tu objeto ActivityScenario. Con createAndroidComposeRule, puedes activar fácilmente la acción de la IU que finaliza la actividad, como se muestra en el siguiente fragmento de código:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @Test fun testResult() {
        composeTestRule.onNodeWithTag("finish_button").performClick()

        val scenario = composeTestRule.activityRule.scenario
        val resultCode = scenario.result.resultCode
        val resultData = scenario.result.resultData
    }
}

Cómo activar acciones en la actividad

Todos los métodos dentro de ActivityScenario son llamadas de bloqueo, por lo que la API requiere que los ejecutes en un subproceso de instrumentación.

Para activar acciones en la actividad que se está probando, usa las APIs de prueba de Compose para interactuar con tus elementos componibles:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @Test fun testEvent() {
        composeTestRule.onNodeWithText("Refresh").performClick()
    }
}

Sin embargo, si necesitas llamar a un método en la actividad, puedes hacerlo de manera segura mediante el uso de onActivity:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.onActivity { activity ->
              activity.handleSwipeToRefresh()
            }
        }
    }
}

Recursos adicionales

Para obtener más información sobre las pruebas, consulta los siguientes recursos adicionales:

Documentación