Patrones de diseño en automatización: PageObjects

¿Si durante nuestros proyectos de automatización de pruebas nos encontramos muchas veces con los mismos problemas… por qué no aplicamos un patrón de diseño?

¿Por qué si en desarrollo de software los patrones de arquitectura son de lo más habituales (léase MVC, MVP, Presentation Model, etc), no ocurre los mismo cuando automatizamos?

¿Si el coste de mantener nuestras pruebas automatizadas es demasiado alto, debido a código duplicado, complejidad… por qué no usamos una estructura que ayude a simplificarlo?

Con la idea de minimizar en gran parte estos problemas, tenemos el Page Object Pattern, patrón de diseño perfectamente aplicable a la automatización de pruebas.

 Introducción

El concepto básico en el que se basa este patrón es el de representar cada una de las pantallas que componen el sitio web o la aplicación que nos interesa probar, como una serie de objetos que encapsulan las características y funcionalidades representadas en la página. De esta manera, nos permite consolidar el código para interactuar con los elementos de una página en cada uno de los PageObjects.

Al crear un PageObject, lo que estamos consiguiendo es crear una capa de abstracción entre el « ¿Qué podemos hacer/ver en la página? », y el « Cómo » se realiza esta acción, simplificando enormemente la creación de nuestras pruebas y reutilizando el código con el que interactuamos con la página en concreto. Y a la vez, cualquier cambio que se produzca en la UI únicamente afectará al PageObject en cuestión, no a los test ya implementados.

Esto se debe a que un test nunca debe manipular directamente elementos de la página (UI), si no que este manejo debe realizarse a través del PageObject correspondiente que representa la página. Para entendernos, el PageObject se convierte en una API con la que fácilmente podemos encontrar y manipular los datos de la página.

solde1

Podemos encontrarnos con que una página corresponda a más de un PageObject, si se da el caso de que algunas áreas de la página son lo suficientemente significativas. Por ejemplo, en una página web, podemos tener un PageObject para el header y otro para el body.

 

Detalles de la implementación

Una de las opciones de las que disponemos es crear, en primer lugar, una clase “básica”, que posteriormente será la que extenderán cada uno de los distintos PageObjects que vayamos implementando. Esta PageBase nos aporta la estructura básica y las propiedades generales que utilizaremos:

solde2

Y una vez creada esta página, crear los PageObjects necesarios. Un ejemplo de una página de “Login” podría ser:

solde3

Lógicamente, si lo creemos conveniente nos podemos saltar la creación de la PageBase, y crear directamente los distintos PageObjects con todas las propiedades y métodos necesarios.

Como podemos ver en este simple ejemplo, los métodos que interactúan con la página en si, normalmente o bien no nos devolverán ningún parámetro, o bien serán de tipo sencillo, como boolean, string, etc (ej. returnErrorMessage() nos devuelve un String con el mensaje de error de la página de login). Pero cuando se trata de funciones de navegación entre páginas, estas nos devolverán un nuevo objeto PageObject del tipo correspondiente a la página donde navegamos. En el ejemplo superior, si desde la página LoginPage ejecutamos el método loginAs, se realizará el login y consecuentemente se nos devolverá un objeto de HomePage, que corresponde al PageObject de la página principal.

Como consecuencia de este enfoque, será necesario crear métodos en los que la acción a realizar acabe con éxito (ej: loginAs, que nos devuelve la HomePage), y otros en los que la acción no sea correcta (ej: loginWithError, que se mantiene en la LoginPage).

Un ejemplo práctico:

solde4Vamos a plantear un ejemplo real: la página de Login de la web de GMail. El ejemplo a continuación se describe como un ejemplo de Selenium, en Java, pero sería implementable perfectamente con otros lenguajes, …

PageObject:

El GmailLoginPage, el PageObject que modela la página podría implementarse de la siguiente forma:

solde5

Como podemos ver, en este código estamos implementando algunos de los métodos para interactuar con la página (introducir email, password, click en SignIn, etc), en los que enlazamos los elementos de la página de Gmail en si misma (ej. Código driver.findElement(…)).

Tests:

Un test sencillo que simplemente ejecute un login y verifique que se accede al “Inbox” correctamente podría implementarse de la siguiente forma:

solde6

En este test básico, utilizamos la función de loginAs que nos ofrece el PageObject de la página de Login de GMail, así como el de getTitle de la página principal del EmailPage, para validar posteriormente que se ha realizado el acceso de forma correcta.

Tal y como podemos ver, al utilizar el patrón de PageObjects, los test que debemos implementar son sencillos y a la vez intuitivos y entendibles, y una vez realizado el esfuerzo inicial de desarrollar los distintos métodos para interactuar con el objeto, la incorporación de nuevas pruebas se puede realizar en un tiempo razonable.

 

Assertions:

En el ejemplo planteado, al final del test, se incorpora una “assertion” o validación, que será la que indicará si la prueba ha sido satisfactoria o no. No existe una posición única sobre si las assertions deben incorporarse en el PageObject o bien en los tests. La primera opción ayuda a evitar verificaciones duplicadas en las pruebas, pero la responsabilidad del PageObject se complica, al no sólo tener que dar acceso a los objetos, sino también incorporar lógica de validaciones. En el caso planteado, se ha optado por esta segunda opción, para desvincular al máximo la lógica de las pruebas de los objetos en si.

Conclusiones:

Sin duda alguna, los patrones de diseño en desarrollo, nos ofrecen  una solución previamente utilizada y de efectividad probada, así como la correspondiente documentación, con  la que enfrentarse a una serie de problemas comunes dentro del mundo del desarrollo y la automatización de pruebas. Y en concreto, el Page Object Pattern nos ofrece las ventajas de:

–          Reducir la duplicidad de código.

–          Conseguir pruebas más robustas y fácilmente entendibles

–          Mejorar la mantenibilidad de nuestras pruebas funcionales automatizadas, punto que se pone de relevancia cuando tenemos una web o aplicación  que evoluciona rápidamente.

Links:

–          Selenium Wiki – PageObjects

–          Microsoft Developer Network – ¿Qué es un patrón de diseño?

 

 

Más información:

Jordi Soldevila

Jordi Soldevila Corominas – Test Lead – Sogeti España

jordi.soldevila@sogeti.com

Autor: qanewsblog

Sogeti es una compañía tecnológica perteneciente al Grupo Capgemini y especialista en: Testing y Calidad de Software; Soluciones Microsoft y High Tech Consulting. En Sogeti entendemos la importancia de obtener el máximo valor empresarial de sus sistemas de IT, por ello somos líderes mundiales en Testing & QA. Somos creadores de las metodologías estándar del mercado: TMap® (Test Management Approach) y TPI® (Test Process Improvement). ¡Nuestro compromiso es el Testing!

Deja tu comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s