Pruebas funcionales en iOS con Kif

jueves, 26 de marzo de 2015


Un tipo de test que podemos realizar a una aplicación iOS son pruebas de interfaz de usuario, al igual que en Android en iOS disponemos de librerías de terceros que nos ayudan en esta tarea. En este artículo vamos a ver cómo podemos realizar pruebas funcionales o de interfaz de usuario utilizando Kif.

Introducción a Kif

Kif (Keep it Functional) es un framework opensource que permite realizar pruebas de interfaz de usuario sobre aplicaciones nativas en iOS. Se basa en las APIs de Accesibilidad de iOS, vamos a poder hacer test que simulan acciones del usuario como pulsar sobre las vistas, realizar gestos como swipe y escribir texto. Vamos a acceder a los controles a través de AccesibilityLabel, todos las vistas que aparecen en un ViewController como botones, TableView etc.. tienen un AccesibilityLabel que en caso de controles con contenido de texto como un label va a coincidir con el texto que contiene el control por defecto, pero por ejemplo para un TableView al no tener un contenido de texto vamos a tener que asignar un AccesibilityLabel, aquí os dejo la guía de Apple.

El objeto que se utiliza en Kif como centralizador de todas las acciones simuladas es el objeto Tester.

Podemos añadir esta librería mediante Cocoapods y también de forma manual, yo para el ejemplo voy a utilizar Cocoapods porque me resulta más cómodo.

Para añadirlo mediante Cocoapods, esta es la configuración que deberemos añadir en el Podfile para el Target de pruebas donde queremos añadir la dependencia.

target 'ExampleTargetTests', :exclusive => true do
  pod 'KIF', '~> 3.0', :configurations => ['Debug']
end

Accesibility Inspector

Si tenemos dudas de que accesibilityLabel tiene un control en ejecución existe una utilidad en iOS que es el inspector de accesibilidad se puede activar desde Settings > General > Accessibility, aparece un popup que nos indica información de cualquier vista que pulsemos, el primer dato es Label y ese será el accesibility label que tiene el control.



Ejemplo

La aplicación que voy a utilizar para el ejemplo de test de intefaz va a ser el ejemplo del artículo anterior de un menú lateral para navegación. Vamos a crear un test que va a ir navegando por todos los view controllers desde el menú lateral.



Accediendo a los menús mediante texto estático

Una opción que tenemos para pulsar sobre los menús de navegación es utilizar el método tapViewWithAccessibilityLabel del objeto tester. En este caso no es necesario que especifiquemos un AccesibilityLabel porque para los controles que intervienen en la prueba nos vale el que asume por defecto, para el botón de menú por defecto será el nombre de la imagen y para pulsar las filas del menu serán los textos que contiene. Cada vez que abrimos un ViewController tenemos verificar que se abre correctamente, para hacerlo utilizamos el método waitForViewWithAccessibilityLabel y buscamos por el título esperado para el ViewController. Este método tiene un timeout de 10 segundos y si en ese tiempo no encuentra una vista con el accesibilty label espeficificado el test fallará.

- (void)testSideNavigationWithStaticText {
    [tester tapViewWithAccessibilityLabel:@"Menu icon"];
    
    [tester tapViewWithAccessibilityLabel:@"Red View Controller"];
    
    [tester waitForViewWithAccessibilityLabel:@"Red View"];
    
    [tester tapViewWithAccessibilityLabel:@"Menu icon"];
    
    [tester tapViewWithAccessibilityLabel:@"Yellow View Controller"];
    
    [tester waitForViewWithAccessibilityLabel:@"Yellow View"];
}

Accediendo a los menús mediante índice de la fila

Otra opción que tenemos para pulsar sobre los menús de navegación es utilizar el método tapRowAtIndexPath:inTableViewWithAccessibilityIdentifier del objeto tester. En este caso necesitamos acceder al UItableView por el identificador y label de accesibilidad. Al no ser una vista accesible, porque las vistas accesibles sobre las que se pueden interactuar son las celdas, no se puede asignar label desde el interface builder (o yo no consigo como hacerlo) y he tenido que asignarselo desde código en el método viewDidLoad. En este método también utilizamos waitForViewWithAccessibilityLabel para esperar a que cargen los controladores de la parte central.

//sideViewController.m
- (void)viewDidLoad{
   self.tableView.accessibilityIdentifier = @"menuTableView";
   self.tableView.accessibilityLabel =@"menuTableView";
}

//SideMenuExampleTests.m
- (void)testSideNavigationByRowIndex {
    [tester tapViewWithAccessibilityLabel:@"Menu icon"];
    
    [tester tapRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0] inTableViewWithAccessibilityIdentifier:@"menuTableView"];
    
    [tester waitForViewWithAccessibilityLabel:@"Red View"];
    
    [tester tapViewWithAccessibilityLabel:@"Menu icon"];
    
    [tester tapRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0] inTableViewWithAccessibilityIdentifier:@"menuTableView"];
    
    [tester waitForViewWithAccessibilityLabel:@"Yellow View"];
}

Accediendo a los menús dinámicamente

Si número de filas del menú se carga dinámicamente y queremos navegar por todos los menús, se puede utilizar el método waitForViewWithAccessibilityLabel para acceder tableView y preguntarle por el número de filas y mediante un bucle for, navegar por todos los menús utilizando el mismo método tapRowAtIndexPath:inTableViewWithAccessibilityIdentifier de la sección anterior y podemos utilizar el método waitForAnimationsToFinishWithTimeout para esperar hasta que termine de cargar la animación de mostrar el nuevo UIViewController.
- (void)testSideNavigationDynamically {

    [tester tapViewWithAccessibilityLabel:@"Menu icon"];
    
    UITableView *menuTableView = (UITableView *)[tester waitForViewWithAccessibilityLabel:@"menuTableView"];
    
    NSInteger numRows = [menuTableView numberOfRowsInSection:0];
    
    for (NSInteger i = 0; i < numRows;i++) {
        [tester tapRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0] inTableViewWithAccessibilityIdentifier:@"menuTableView"];

        [tester waitForAnimationsToFinishWithTimeout:(2)];
        
        [tester tapViewWithAccessibilityLabel:@"Menu icon"];
    }

Resumen

En este artículo hemos visto como podemos realizar test de interfaz de usuario en iOS utilizando Kif que se basa en las APIs de Accesibilidad para poder realizar gestos, pulsaciones y escribir texto.

Libros relacionados

NSHipster: Obscure Topics in Cocoa & Objective C

iOS Programming: The Big Nerd Ranch Guide

Objective-C Programming: The Big Nerd Ranch Guide

No hay comentarios:

Publicar un comentario