Cómo probar Navigation

1. Antes de comenzar

En codelabs anteriores, aprendiste acerca de la navegación entre actividades. En este codelab, aprenderás algunos enfoques diferentes para probar la navegación mediante pruebas de instrumentación.

Requisitos previos

  • Haber creado directorios de prueba en Android Studio
  • Haber escrito pruebas de instrumentación y de unidades en Android Studio

Qué aprenderás

  • Cómo usar pruebas de instrumentación para probar la navegación física entre actividades o fragmentos

Requisitos

  • Una computadora que tenga Android Studio instalado
  • El código de solución de la app de Words

Cómo descargar el código de partida para este codelab

En este codelab, agregarás pruebas de instrumentación al código de solución para la app de Words.

Para obtener el código necesario para este codelab y abrirlo en Android Studio, haz lo siguiente:

Obtén el código

  1. Haz clic en la URL proporcionada. Se abrirá la página de GitHub del proyecto en un navegador.
  2. En esa página, haz clic en el botón Code, que abre un cuadro de diálogo.

5b0a76c50478a73f.png

  1. En el cuadro de diálogo, haz clic en el botón Download ZIP para guardar el proyecto en tu computadora. Espera a que se complete la descarga.
  2. Ubica el archivo en tu computadora (probablemente en la carpeta Descargas).
  3. Haz doble clic en el archivo ZIP para descomprimirlo. Se creará una carpeta nueva con los archivos del proyecto.

Abre el proyecto en Android Studio

  1. Inicia Android Studio.
  2. En la ventana Welcome to Android Studio, haz clic en Open an existing Android Studio project.

36cc44fcf0f89a1d.png

Nota: Si Android Studio ya está abierto, selecciona la opción de menú File > New > Import Project.

21f3eec988dcfbe9.png

  1. En el cuadro de diálogo Import Project, navega hasta donde se encuentra la carpeta de proyecto descomprimido (probablemente en Descargas).
  2. Haz doble clic en la carpeta del proyecto.
  3. Espera a que Android Studio abra el proyecto.
  4. Haz clic en el botón Run 11c34fc5e516fb1c.png para compilar y ejecutar la app. Asegúrate de que funcione como se espera.
  5. Explora los archivos del proyecto en la ventana de herramientas Project para ver cómo se configuró la app.

2. Descripción general de la app de partida

La app de Words consiste en una pantalla principal que muestra una lista en la que cada elemento es una letra del alfabeto. Si haces clic en una letra, navegarás a una pantalla que muestra una lista de palabras que comienzan con esa letra.

3. Prácticas recomendadas

En Kotlin, la convención habitual para asignar nombres a funciones es usar "mayúsculas mediales" en la que la primera letra del nombre de la función esté en minúscula y la primera letra de las palabras posteriores se escriba en mayúscula (por ejemplo, myCamelCaseFunction()). Los métodos de prueba que escribimos hasta ahora usaron todos letras minúsculas y guiones bajos entre las palabras (por ejemplo, my_test_function()). Esto se debe a que se busca que los nombres de las funciones sean detallados de modo que indiquen de forma explícita lo que se está probando. De esta manera, si la prueba falla, el nombre indicará claramente lo que falló. En Kotlin, podemos incluso usar espacios en los nombres de métodos si unimos el nombre del método entre acentos graves, de la siguiente manera: ``prueba de función con espacios (). Ten en cuenta que el acento grave es diferente a la comilla simple. Se puede encontrar en la tecla con la tilde (~). Esto ayuda a crear nombres de funciones legibles por humanos que resulten fáciles de identificar en caso de que se produzca una falla.

Sin embargo, este enfoque tiene una salvedad: esta implementación requiere configuración. Ten en cuenta que esta sección es opcional. Recomendamos que lo leas, pero no necesitas seguir ninguno de los pasos hasta la sección Crea el directorio de pruebas de instrumentación.

  1. Observa que tener espacios en el nombre de la función solo funciona si te orientas al nivel de API 30 en Android. De lo contrario, verás un error similar al siguiente:

4333fe8605801dba.png

Para cambiar la API, ve a app/build.gradle y modifica la minSdkVersion o la targetSdkVersion:

a6207c31c66ca185.png

En este caso, la targetSdkVersion se estableció en 30, que es lo que se requiere. Sin embargo, la minSdkVersion es 19, por lo que tendríamos que cambiarla a 30 para que se permitan los espacios en los nombres de las funciones. Esto no siempre resulta práctico, por lo que es bueno incluir esta función, pero no es un requisito.

  1. Incluso si te orientas al nivel de API 30, verás que el método está subrayado en rojo con el mensaje "Identifier not allowed in Android Projects".

d1330d69cc2472b1.png

Igualmente, la prueba se ejecutará hasta completarse. Para deshacerte del subrayado, navega a la configuración o las preferencias de Android Studio y ve a Editor -> Inspections -> Kotlin Android -> Illegal Android Identifier -> Tests.

acc4a31499bdb25.png

A continuación, desmarca la casilla Tests y haz clic en Apply o en OK.

aeb57d303996a3de.png

Ahora tus métodos ya no estarán subrayados en rojo, siempre que incluyas el nombre del método entre acentos graves.

a54f3eff47697024.png

4. Crea el directorio de prueba

Crea un directorio de pruebas de instrumentación para la app de Words.

5. Crea una clase de pruebas de instrumentación

Crea una clase nueva llamada NavigationTests.kt.

9d9ee307b4773b7.png

6. Escribe la prueba de navegación

  1. Especifica un ejecutor de pruebas.
@RunWith(AndroidJUnit4::class)
  1. Luego, inicia la actividad principal.
@get:Rule
val activity = ActivityScenarioRule(MainActivity::class.java)
  1. Ahora, crea un método llamado navigate_to_word().
@Test
fun navigate_to_word() {
}
  1. En los métodos navigate_to_word(), debemos elegir un elemento de lista para seleccionar. El elemento que elegimos es arbitrario y podemos realizar esto de varias maneras. Podemos elegir un elemento según su posición en el adaptador, o bien un elemento en función del texto (es decir, la letra) que contiene. Recuerda que si quieres interactuar directamente con el elemento RecyclerView, necesitarás la siguiente dependencia:
dependencies {
    ...
    androidTestImplementation
‘com.android.support.test.espresso:espresso-contrib:3.0.2'
}

Por otro lado, si eliges seleccionar un elemento por texto, puedes usar el método withText() que usaste en codelabs anteriores. Es importante tener en cuenta que, si usas este enfoque y el texto no aparece en la pantalla, la prueba fallará. Revisaremos ese tema más adelante.

  1. Trata de probar ambos métodos. Recuerda que nuestro objetivo es hacer clic en el componente de IU una vez que lo encuentres.

Ambos enfoques se muestran aquí con la intención de hacer clic en el elemento de la letra "C" como ejemplo.

onView(withText("C")).perform(click())
onView(withId(R.id.recycler_view))
   .perform(RecyclerViewActions
       .actionOnItemAtPosition<RecyclerView.ViewHolder>(2, click()))

Tómate un momento para examinar ambos enfoques en profundidad. Si ejecutas cualquiera de ellos y miras tu emulador o dispositivo, verás que ambos funcionan. El uso de RecyclerViewActions requiere más código, pero tiene la ventaja distintiva de poder hacer clic en cualquier elemento sin trabajo adicional. Prueba el primer enfoque, pero cambia la letra "C" a "Z" y vuelve a ejecutar la prueba. Verás que la prueba falla con el siguiente error: androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with text: is "Z".

3c518d4b00624af3.png

Eso se debe a que "Z" está al final de la lista y fuera de la pantalla cuando iniciamos la app y, para llegar a ella, debemos desplazarnos hacia abajo. El enfoque de RecyclerViewAction controla esto de manera inherente. Intenta pasar 25 como el valor de posición y observa el emulador o dispositivo.

  1. Si realizaste los ejemplos anteriores, verás que la ejecución de la siguiente actividad fue exitosa, pero queremos confirmarlo con una aserción. Si ejecutas la app y haces clic en cualquier elemento de la lista, verás que el título de la barra de la aplicación dice "Words That Start With __", donde el espacio en blanco corresponderá a la letra en la que hayas hecho clic. Podemos usar esta información para comprobar que la navegación funcionó correctamente. Solo debemos declarar que se muestra la cadena correcta, seguida de la letra en la que hicimos clic. Realizaste aserciones similares en codelabs anteriores, así que trata de hacer esto por tu cuenta.
onView(withText("Words That Start With C")).check(matches(isDisplayed()))

7. Lección conceptual y prácticas recomendadas

En las pruebas, se usan dos términos muy importantes: "falso positivo" y "falso negativo".

Un "falso positivo" se da cuando una prueba produce un resultado de aprobación a pesar de haber un problema por el cual la prueba debía fallar. Del mismo modo, un "falso negativo" se da cuando una prueba muestra un resultado fallido a pesar de que la información sea correcta y la prueba debería haberse aprobado.

En la prueba que escribimos arriba, codificamos de forma fija la cadena que buscamos. Desde la perspectiva del código, sería más limpio compilar la adena ca partir de los recursos de cadenas, como se hizo en la app. El funcionamiento es un poco distinto al que usa en el código normal de la app, pero es posible. Sin embargo, compilar la cadena de esta manera podría fallar, ya que, técnicamente, se trataría de una lógica empresarial. Si la compilación de la cadena en la prueba falló de la misma manera que lo hizo en el código de la app, esto podría arrojar un falso positivo. Esto se debe a que ambos fragmentos de código compilan la misma cadena de manera incorrecta. Por lo tanto, el texto incorrecto de la prueba coincide con el texto incorrecto que se muestra en la app. En consecuencia, es mejor codificar la cadena de forma fija con el valor que esperamos.

8. Código de solución

9. Felicitaciones

En este codelab, hicimos lo siguiente:

  • Aprendimos a crear nombres de funciones detallados para las pruebas
  • Aprendimos a probar la navegación física con actividades o fragmentos
  • Conocimos más sobre los "falsos positivos" y "falsos negativos"