Selenium y Selenium Grid

Selenium nos permite realizar pruebas funcionales en aplicaciones web principalmente, aunque también es posible utilizarlo para otro tipo de aplicaciones como Android, por ejemplo.

Se basa en el uso de unos controladores (drivers) que permiten manejar el navegador, desde fuera del navegador, cada navegador tiene el suyo. El movimiento se demuestra andando, así que vamos a ver directamente como funciona

Instalación de Selenium

Descargaremos el driver de esta página. En este ejemplo vamos a utilizar Internet Explorer, así que descargaremos el zip que contienen el driver y los descomprimiremos en una carpeta de nuestro equipo. También descargaremos el jar, y lo dejaremos en la misma carpeta. Incluiremos dicha carpeta en la variable PATH.

Para el navegador Firefox ya viene instalado el driver por defecto.

Selenium IDE

Selenium IDE es un complemento de Firefox que permite grabar las navegaciones realizadas para que posteriormente sean reproducidas. El problema de esta herramienta es que el código generado es obsoleto, difícil de mantener y no sigue los patrones de diseño. Puede ser útil para grabar una prueba rápida, pero no es adecuado si lo que queremos es mantener pruebas con cierto grado de complejidad.

Selenium IDE

Selenium IDE

Uso del driver local

El primer paso como siempre, es incluir en nuestro proyecto la dependencia Maven

Una vez que tenemos las librerías necesarias, podemos acceder al driver para el manejo del navegador que nos interese de este modo:

Así de fácil, a través de este objeto ya podemos manejar el navegador.

Selenium Webdriver API

Vamos a ver las operaciones que se pueden realizar a través del API que permite manejar el Webdriver. Las operaciones que se pueden realizar son:

  • Manejo del navegador (abrirlo, cerrarlo, maximizarlo…).
  • Encontrar, seleccionar y manipular elementos HTML.
  • Utilidades de depuración

Nos encontramos que a la hora de buscar, podemos:

  • Buscar todos los elementos de la página que cumplan algún criterio (findElements).
  • Buscar un único elemento (findElement).

En el último caso (findElement) tenemos:

  • Si existe más de un elemento, nos devolverá el primero que encuentre
    En el caso de que no encuentre el elemento, lanzará la excepción NoSuchElementException

Comprobar que un elemento no este presente

  • Si queremos comprobar que un elemento no está presente, se recomienda utilizar el método findElements, y seguidamente comprobar que el tamaño de la lista de elementos devueltos es igual a cero.

Los mecanismos para buscar son los siguientes:

Web Driver API: Localizando elementos

Web Driver API: Localizando elementos

De la tabla que se muestra arriba, prestaremos especial atención a la búsqueda por XPATH. XPath (XML Path Language) es un lenguaje que permite construir expresiones que recorren y procesan un documento XML. Permite buscar y seleccionar teniendo en cuenta la estructura jerárquica del XML. Fue creado originalmente para su uso en el estándar XSLT.
Selenium soporta la versión de XPath que tenga el navegador. En IE 6, 7, y 8 es la 1.0
Existen herramientas para desarrolladores que nos pueden ser muy útiles:

  • Firefox: Xpath Checker, FirePath
  • Crome: Xpath Helper

En esta página se puede encontrar un excelente tutorial de Xpath

WebElement

El método findElement devuelve una instancia de WebElement, que encapsula toda la información relacionada con el DOM del elemento y que permite interactuar con él. Algunos de los métodos más interesantes de WebElement son:

  • clear()
  • click()
  • getAttribute(String name)
  • getTagName()
  • getText()
  • getValue()
  • isEnabled()
  • isSelected()
  • sendKeys(CharSequence keysToSend)
  • setSelected()
  • submit()

El patrón Page Object

Si queremos implementar pruebas funcionales y que estas no se conviertan en una maraña de código difícil de mantener, tenemos que adoptar los patrones que nos garantizan las mejores prácticas de desarrollo.

El patrón Page Object permite separar la funcionalidad lógica de una aplicación, con el modo de interactuar con la propia funcionalidad. Actúa como una API exponiendo las funcionalidades de la página como servicios y ocultando los detalles de implementación e interacción con su código HTML. Consiste en crear un objeto por cada una de las páginas con las que queremos trabajar, de modo que dichos objetos expongan las funcionalidades de cada página abstrayéndonos de la estructura interna de la página. Cuando nos movemos entre páginas, se nos debe devolver en objeto que represente la página a la que queremos acceder.
El Page Object es la única entidad que posee el conocimiento de la estructura HTML y no deben realizar aserciones, esto debe realizarse en los test, en la medida de lo posible.

El patrón PageFactory

Permite inicializar atributos de los Page Object, de modo que nos evitamos tener que escribir expresiones del tipo:

Se inicializan los atributos con la anotación @FindBy por ejemplo:

Para que se carguen los atributos no basta únicamente con anotarlos. Hay que realizar una llamada a PageFactory para que inicialice completamente el Page Object que vamos a utilizar. Por ejemplo:

Como se puede ver aquí se recupera un PageObject a través de la factoría. Vamos a ver un ejemplo práctico.

Ejemplo práctico: Buscar www.notodocodigo.com en Google

En este ejemplo vamos a realizar dos tests, el primero busca el texto “no todo código” en Google y pulsa en el botón “Voy a tener suerte”. El resultado esperado es que se muestra este blog. El segundo test, busca el mismo texto y comprueba que aparece en primer lugar en las sugerencias de google. Veamos el código:

Como se puede ver, en el método setUp() inicializamos el driver local. Estamos utilizando Internet Explorer, pero podríamos utilizar Firefox, simplemente descomentando la línea.

En el método tearDown() invocamos a “driver.quit()” para cerrar el navegador.

En los tests recuperamos el PageObject GoogleHomePagea través de PageFactorypara conseguir su inicialización. Esta clase, contiene los elementos necesarios para manipular el buscador de Google según nuestros fines. Las acciones que se van a realizar sobre el buscador serán, realizar una búsqueda normal, y realizar una búsqueda y pulsar el botón “Voy a tener suerte”, de modo que a tal fin se crean los métodos “voyATenerSuerte()” y “buscar()”.  Como se puede ver, al realizar cualquiera de las acciones, nos lleva a otra página distinta, por lo tanto se devuelve un nuevo PageObject que encapsula la funcionalidad de las nuevas páginas. Veamos estos PageObjects:

Como se puede ver, se inicializan los elementos de la página con la anotación @FindBy. El primer método devuelve el PageObject con la lista de resultados de Google:

El último PageObject que necesitamos, es precisamente el que se corresponde con Notodocodigo:

Si ejecutamos el ejemplo podemos comprobar el resultado.

Selenium Server

Hemos visto como ejecutar Selenium en local, en nuestro propio equipo. Lo normal será que queramos ejecutar nuestras pruebas en una máquina remota de modo desatendido. Para ello arrancaríamos Selenium Server para que de este modo reciba las ordenes de manejo del navegador desde cualquier lugar.

Selenium Server es un servidor (Jetty) que maneja los driver del navegador y permite aceptar peticiones remotas para manejar dicho navegador. Como se ha comentado al principio de este tutorial, podemos descargar “selenium-server-standalone-2.42.2.jar” de esta página. Para lanzar la ejecución del servidor, abriríamos un terminal y situándonos en el lugar donde lo hayamos descargado introduciríamos lo siguiente:

Como se puede ver, levantamos el servidor en el puerto 4444. Ahora podemos ejecutar el driver de este modo:

Selenium Grid

Selenium grid permite levantar un servidor hub, al que se pueden conectar tantos nodos como queramos. Cada uno de estos nodos es un servidor de selenium donde se pueden ejecutar las pruebas. Tendríamos de este modo una “granja de servidores” compuesta por una serie de nodos donde manejar el navegador para realizar las pruebas. Cada uno de estos nodos se puede configurar para manejar un determinado tipo de navegador.

Todas las pruebas se lanzan apuntando a un único punto, el hub, y es este hub el encargado de encolar las peticiones y distribuirlas por los distintos nodos.

 

Selenium Hub

Selenium Hub

Para arrancar el HUB, ejecutaríamos en un terminal lo siguiente:

Para registrar un nodo en el HUB, en la máquina donde queramos levantar el nodo, ejecutaríamos:

Para conocer los parámetros de configuración añadimos -h

Una vez levantado el hub podemos acceder a la consola, para conocer los nodos que están levantados, que navegadores soportan y si están en ejecución o no. Para ello accederíamos a la siguiente url: http://<iphub>:4444/grid/console/

Por ejemplo, en la siguiente imagen, vemos dos nodos que soportan todos los navegadores y en los que en uno de ellos se indica que se esta ejecutando Internet Explorer (marcado con una flecha).

Selenium hub console

Selenium hub console

Bueno, aquí terminamos con este pequeño artículo sobre Selenium. Si te ha gustado puedes añadir un comentario. No olvides que los comentarios son moderados y no se muestran instantáneamente.

3 comentarios:

  1. Hola,

    ¿Qué ventaja tiene utilizar PageFactory? Porque no puedo tener una Factoría por todos los elementos que quiero buscar en el DOM.

    Muchas gracias, Buen artículo.

  2. Buenas, estoy intentando ejecutar mis test sobre mi grid en ubuntu usando chromedriver, pero al lanzarlos no se abre el navegador, aunque si que parece que esté ejecutnadolos porque pasea los ficheros cucumber hasta el caso 3, pero sin abrir ningun navegador. Donde puede estar el problema? En windows lo lanzo igual y los ejecuta sin problemas, pero en ubuntu nada.

  3. Sí estás ejecutando en remo tendrás que instalar y arrancar el buffer virtual de ventanas. Busca información sobre xvfb

    Un saludo

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *