Cómo probar las actividades de tu app

Las actividades funcionan como contenedores de 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 a 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 tu 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 de manera correcta 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 a medida que las actividades de la app pasan por los diferentes estados en sus ciclos de vida.

Cómo administrar el estado de una actividad

Un aspecto clave a la hora de probar las actividades de tu app implica colocar las actividades de tu app en estados particulares. Para definir esta parte "determinada" de tus pruebas, usa instancias de ActivityScenario, que forma parte de la biblioteca de AndroidX Test. Con esta clase, puedes colocar tu actividad en estados que simulan eventos a nivel del dispositivo.

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

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

Crea 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 hace la transición de esta al estado RESUMED. Este estado indica que tu actividad está en ejecución y que los usuarios pueden verla. En este estado, puedes interactuar con los elementos View de tu actividad mediante las pruebas de IU Espresso.

Google recomienda que llames a close en la actividad cuando se complete la prueba. Esto limpia los recursos asociados y mejora la estabilidad de las pruebas. ActivityScenario implementa Closeable, por lo que puedes aplicar la extensión use, o try-with-resources en el lenguaje de programación Java, para que la actividad se cierre automáticamente.

Como alternativa, puedes usar ActivityScenarioRule para llamar automáticamente a ActivityScenario.launch antes de cada prueba y ActivityScenario.close en la desconexión de la prueba. En el siguiente ejemplo, se muestra cómo definir una regla y obtener de ella una instancia de una situación:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule var activityScenarioRule = activityScenarioRule<MyActivity>()

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

Cómo pasar la actividad a un nuevo estado

Para llevar 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 una 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 actividad 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 redirecciona 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

Cuando un dispositivo tiene pocos recursos, el sistema puede destruir una actividad y requerir que tu app la vuelva a crear 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 anotado con @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 obtener el código de resultado o los datos asociados con una actividad finalizada, obtén el valor del campo result dentro de tu objeto ActivityScenario, como se muestra en el siguiente fragmento de código:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testResult() {
        launchActivity<MyActivity>().use {
            onView(withId(R.id.finish_button)).perform(click())

            // Activity under test is now finished.

            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 el subproceso de instrumentación.

Para activar acciones en la actividad que estás probando, usa los comparadores de vistas de Espresso a fin de interactuar con los elementos de tu vista:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use {
            onView(withId(R.id.refresh)).perform(click())
        }
    }
}

Sin embargo, si necesitas llamar a un método en la actividad, puedes hacerlo de forma segura implementando ActivityAction:

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