¿Cómo crear y ejecutar un test?

¡Hola de nuevo developers!

Hoy vamos con la segunda parte del post: «Qué es el UITesting y para qué nos sirve».

En este post veremos cómo configurar un proyecto UITest en Android e iOS y cómo crear un Test, así como los pasos para ejecutarlo.

¿Te animas?

 

Configuración del proyecto iOS

La configuración del proyecto de iOS es la más complicada, y la que puede acarrear más problemas.

Además del proceso de creación, para que los UITest funcionen correctamente, en iOS hay que seguir los siguientes pasos:

 

  1. Añadir al proyecto de iOS el NuGet «Xamarin Test Cloud Agent
  2. En la configuración del proyecto añadiremos un «Define Symbols«, en concreto ENABLE_TEST_CLOUD.
  3. Añadir el siguiente código en nuestro AppDelegate
    #if ENABLE_TEST_CLOUD#endif
  4. Xamarin.Calabash.Start();

 

Una vez hecho esto, tendremos el proyecto de iOS configurado teniendo en cuenta lo siguiente:

En Android los elementos de una vista tienen un identificador por defecto que es el que se utiliza para encontrar el elemento en un Test. En iOS, por defecto, esto no pasa. Por lo tanto, buscamos en la vista por textos. En ocasiones esto no funciona, por lo tanto hay que incluir en la carga de la vista (ViewDidLoad), el AccessibilityIdentifier del elemento.

Configuración proyecto Android

No hace falta más configuración que la que ya hacemos habitualmente para instalar aplicaciones externas en el dispositivo (Habilitar debug en el dispositivo).

¿Cómo creamos un test? 

Cuando se crea un Test, lo primero es inicializar la configuración de cada plataforma, para identificar el dispositivo en el que se quiere ejecutar el test, donde «iOSApp» y «AndroidApp«, implementan la misma interfaz:

iOSApp app = ConfigureApp.iOS.StartApp();

ó

AndroidApp app = ConfigureApp.Android.StartApp();

 

Para identificar la clase del test como para un único entorno, se le tiene que añadir la etiqueta «TestFixure«.

Dentro de la clase podemos utilizar más etiquetas, como por ejemplo, «SetUp» y «Test«.

La primera se utiliza para asegurarnos que una función se ejecuta siempre antes de cada test, y la segunda para indicar que la función es un test, y así podemos verlo como tal en el panel de Unit Test.

Para realizar los test utilizamos la variable «app«, que como se muestra al principio, se inicializa dependiendo de la plataforma, y en ambos casos implementa la misma interfaz “Xamarin.UITest.IApp”, por lo que las opciones que tenemos son las mismas. Esta interfaz tiene los métodos necesarios para poder realizar todo lo imprescindible en la interfaz simulando la interacción de un usuario.

Con todo configurado, se puede crear el primer test, para el cual se necesitará obtener referencias a las vistas que son visibles en la pantalla.

Muchos métodos en Xamarin.UITest toman un delegado Func <AppQuery, AppQuery>  como parámetro para localizar las vistas. Este delegado a su vez utiliza AppQuery, que es el núcleo de cómo Xamarin.UITest localiza vistas.

De los métodos que proporciona AppQuery, el método Marked es uno de los más simples y flexibles. Este método utiliza una heurística para tratar de localizar vistas. Es importante entender que IApp tiene muchos métodos para interactuar con una aplicación. Estos métodos utilizan un Func <AppQuery, AppQuery> para obtener una referencia a la vista y poder interactuar con esta.

 

Algunos de los métodos más interesantes proporcionados por AppQuery son:

  • Button: Localiza uno o más botones en la pantalla
  • Class: Intentará localizar vistas que sean de una clase especificada
  • Id: Intentará localizar una vista con el Id especificado
  • Index: Devuelve una vista de una colección de vistas coincidentes. Usado generalmente conjuntamente con otros métodos
  • Marked: Se verá en descripción más abajo
  • Text: Devolverá las vistas que contienen el texto proporcionado
  • TextField: Devolverá las vistas que coincidan con su Android EditText o iOS UITextField

 

Por ejemplo, el siguiente método muestra cómo simular un toque en un botón: 

app.Tap (c => c.Marked ( » ButtonSave «));

Esto hace posible encadenar múltiples invocaciones de AppQuery para localizar vistas. Considere este ejemplo más complicado de tocar en una vista:

app.Tap(c => c.Marked(«Example»).Parent().Class(«AppointmentListCell»).Indice(0));

 

Ahora vamos a ver el método Marked, ya que funciona de manera distinta dependiendo de la plataforma:

iOS

Las vistas de iOS se localizan utilizando uno de los siguientes atributos:

  • AccessibilityIdentifier de la vista
  •  AccessibilityLabel de la vista

Android

Las vistas de Android se localizan utilizando uno de los siguientes atributos:

  • Id de la vista
  • ContentDescription de la vista
  • Text de la vista

 

Ya solo nos queda hacer una acción sobre la vista que hemos obtenido de la pantalla. La interfaz “Xamarin.UITest.IApp” tiene bastantes métodos para actúar sobre estas vistas, pero las más comunes son:

  • Tap: Hace click sobre la vista
  • WaitForElement: Espera a que se cargue la vista en la pantalla. Tiene un time out por defecto que se puede modificar pasándolo como parámetro.
  • EnterText: Introduce el texto indicado en la vista
  • DismissKeyboard: Oculta el teclado del dispositivo. Si el teclado está sobre una vista, al intentar encontrarla daría un error.
  • SrollTo: Hace scroll de la pantalla hasta que se encuentre una determinada vista.
  • ScrollDown: Hace scroll hasta que lo primero que se vea sea lo último que se podía ver antes de este
  • ScreenShot: Toma una captura de la pantalla de la aplicación en su estado actual y la guarda en el disco

TestRecorder

Xamarin ofrece una herramienta para hacernos la creación del test mucho más sencilla: TestRecorder

Para ello, descargaremos la aplicación desde este link. 

Una vez tenemos ese paquete creado, para configurar el Test Recorder, abriremos la aplicación, seleccionaremos el dispositivo donde queremos grabar el test, y al ser la primera vez, tendremos que buscar el archivo en nuestra máquina.

Una vez todo seleccionado, la aplicación se lanzará en el dispositivo seleccionado:

Resultado del TestRecorder y Adaptación

Una vez está en ejecución la aplicación, solo tenemos que pulsar en el botón «Record«, y en el panel derecho empezaremos a ver cómo van apareciendo los eventos del dispositivo.

Se puede observar cómo, por cada acción, el Recorder nos hace una captura de pantalla. Esto no se hace en local cuando pasamos el test, si no que sirve para cuando usemos TestCloud. 

Una vez terminado de grabar el Test que queremos ejecutar, nos dirigiremos a la parte superior derecha y pulsaremos Export, de esta manera podemos generar una clase con el test o copiar el código.

Este código lo copiamos o exportamos en nuestros test. Muchas veces requiere que lo adaptemos porque no queremos que se hagan por cada acción una captura de pantalla. Para ello, con pulsar en el panel izquierdo en el icono de la cámara, podemos quitar esa línea.

Ejecución de una línea

Para ejecutar un test, tenemos que tener en cuenta los siguientes aspectos:

  • Siempre que editemos nuestra aplicación, tendremos que ejecutar en el dispositivo antes de ejecutar el test, ya que el test se ejecuta sobre la aplicación instalada.
  • Siempre que creemos un test, debemos hacer build de la solución de UITesting para que el proyecto reconozca los nuevos test.
  • En caso de querer ejecutar sobre dispositivo iOS los test, aplica igual que una aplicación normal. Necesitamos tener nuestros certificados y respectivos perfiles.

Para ejecutar en local un Test:

  1. Seleccionamos la configuración del proyecto en la que hemos configurado el test en caso de iOS (debug). En caso de Android da igual:
  2. Seleccionamos dispositivo donde queremos ejecutar el test y nos aseguramos que en el pad de Test aparece seleccionado, si no, lo seleccionamos también en el pad. En caso de no ser así: botón derecho en el dispositivo y nos saldrá una lista de los disponibles:
  3. Botón derecho sobre el test que queremos ejecutar «Run Test» ejecutará el test en el dispositivo seleccionado:
  4. Como se puede ver en esta captura, en este proyecto tenemos varios test principales que engloban varias acciones. Si seleccionamos el nivel más bajo, solo se ejecutará ese test, y según vamos subiendo, se ejecutan de seguido todos los hijos de éste:

 

La ejecución de un test puede dar dos resultados:

  • Éxito: Se muestra un tick verde, y en la consola un «Test Success«
  • Error: Se muestra un icono en rojo, en la consola veremos un «Test Fail«, y expandiendo este, nos mostrará el error: