Pruebas funcionales sin cabeza con selenio y PhantomJS

Construyamos un sistema para realizar pruebas funcionales en aplicaciones web, utilizando Selenium y PhantomJS. El sistema resultante nos permitirá escribir escenarios de prueba sencillos en JavaScript y probarlos tanto en navegadores reales como en un simulador sin cabeza.


Escogiendo Componentes

El inconveniente obvio de Selenium es que requiere un escritorio gráfico completo para todas las pruebas..

Para comenzar, debemos elegir un motor de control o emulación del navegador para simular un usuario final. Durante mucho tiempo, el jugador principal en este campo fue el selenio, y aún lo es. Selenium permite el control automatizado de navegadores reales en sistemas operativos reales, que es su principal ventaja: puede estar absolutamente seguro de que las pruebas representan la realidad lo más cerca posible..

El inconveniente obvio de Selenium es que requiere un escritorio gráfico completo para todas las pruebas. Como resultado, sus pruebas pueden llegar a ser lentas. Sin embargo, Selenium puede ser fantástico, si tiene los recursos necesarios para configurar máquinas virtuales para diferentes sistemas operativos y conectarlos todos juntos.

En el extremo opuesto del espectro se encuentra PhantomJS: un proyecto pequeño pero excelente, que ejecuta un motor WebKit con acceso completo a JavaScript, pero sin la parte gráfica. PhantomJS es muy fácil de configurar, se ejecuta en cualquier máquina y es significativamente más rápido.

Selenium ahora puede controlar PhantomJS de la misma forma que lo hace con cualquier otro navegador..

PhantomJS, al ser un WebKit completo, cubre el 90% de sus necesidades de pruebas funcionales. Después de todo, si su aplicación se ejecuta en WebKit correctamente, es probable que se ejecute correctamente en otros navegadores.. Obviamente, esto excluye Internet Explorer 6-8.

Sin embargo, a medida que su proyecto se vuelve cada vez más popular, el 10% restante se convierte en un problema importante. Si su conjunto de pruebas funcionales se configura en PhantomJS directamente, sería una molestia reescribir las pruebas de selenio.

Por suerte, recientemente, cerca del final de la cola de 2012, recibimos un regalo en forma de enlaces PhantomJS a Selenium. En otras palabras, Selenium ahora puede controlar PhantomJS de la misma forma que lo hace cualquier otro navegador..

Dado que Selenium, en sí mismo, no necesita una configuración complicada y puede ejecutarse en cualquier lugar, podemos usar enlaces de Selenium para controlar PhantomJS y cubrir el 90% de nuestras necesidades de prueba. Si más tarde necesita pruebas más potentes, puede configurar conexiones de navegador adicionales para Selenium sin cambiar una sola línea en su código.

Por lo tanto, nuestra elección para el motor del navegador es Selenium con PhantomJS.

Describiendo Pruebas

Selenium ofrece enlaces en los lenguajes de programación más populares, por lo que podemos elegir un idioma de acuerdo con nuestras necesidades. Este es quizás el artículo más controvertido de este artículo: Considero que JavaScript es la mejor opción para describir pruebas funcionales para sitios web y aplicaciones web..

  • No importa qué tecnología de back-end use, su front-end siempre usará JavaScript (Esto se aplica incluso si utiliza un lenguaje que se compila a JavaScript de vainilla, como CoffeeScript o TypeScript.). Como tal, JavaScript siempre será un lenguaje comprendido por al menos una persona en su equipo.
  • A continuación, considere la posibilidad de que sus pruebas funcionales sean escritas por no programadores. La popularidad de JavaScript en la interfaz de usuario, combinada con la expresividad en la capacidad de crear lenguajes claros específicos de dominio, claramente permite que más personas escriban pruebas funcionales.
  • Por último, es natural controlar un navegador de prueba con JavaScript, dado que es altamente asíncrono, y es con lo que controlamos el navegador diariamente..

Los enlaces de selenio para JavaScript son llamados, webdriverjs. Aunque el proyecto es menos maduro que los controladores oficialmente compatibles para Java, C #, Ruby y Python, sin embargo, ya contiene la mayoría de las funcionalidades que requerimos.

Prueba de funcionamiento

A los efectos de este artículo, Mocha con Chai ha sido seleccionado..

Finalmente, necesitamos un corredor de prueba, o una aplicación para ejecutar las pruebas por nombre, e imprimir bastante la salida, al tiempo que observamos cuántas pruebas tuvieron éxito o fallaron. Este corredor de prueba también debería ofrecer una biblioteca de aserciones, que permite al codificador expresar si una prueba se realiza correctamente o no..

La elección es absolutamente libre aquí. Hay muchos corredores de prueba de JavaScript, pero a los efectos de este artículo, se ha seleccionado Mocha con Chai. Mocha proporciona una considerable cantidad de flexibilidad, una amplia variedad de formatos de salida y la popular sintaxis tipo jazmín. Chai te permite escribir aserciones descriptivas de tipo BDD.


Preparar

Aquí está la última pila que usaremos:

  1. Mocha - corredor de prueba
  2. Chai - biblioteca de afirmaciones
  3. webdriverjs - enlaces de control del navegador
  4. Selenium - abstracción del navegador y fábrica en funcionamiento.
  5. PhantomJS - navegador rápido sin cabeza

Node.js y npm

Debido a que la mayoría de nuestra pila está basada en JavaScript, necesitamos node.js y npm. Ambas son herramientas comunes en la comunidad, y asumiré que ya las tienes configuradas. Si no lo hace, use el instalador en el sitio web node.js. No te preocupes Si algo sale mal, hay muchas guías de instalación de Node disponibles en la web..

Mocha, Chai y webdriverjs

Los tres de estos pueden ser instalados, usando npm:

sudo npm instalar -g mocha chai webdriverjs

Alternativamente, puede instalarlos localmente en el directorio donde se encuentran sus pruebas:

npm instalar mocha chai webdriverjs

Selenio

Descargar Selenium Server. Se distribuye como una sola. tarro archivo, que se ejecuta simplemente:

java -jar selenium-server-standalone-2.28.0.jar

Tan pronto como ejecute este comando, iniciará un servidor al que su código de prueba se conectará más adelante. Tenga en cuenta que necesitará ejecutar Selenium Server cada vez que ejecute sus pruebas.

PhantomJS

Versión rapida

Utilizar npm para instalar PhantomJS a nivel mundial:

sudo npm install -g phantomjs

Otras opciones

Requerimos una versión nueva de PhantomJS - al menos 1.8. Esto significa que los paquetes provistos por su administrador de paquetes (apt-get, MacPorts, ...) probablemente estarán desactualizados.

Puede instalar usando npm sin una instalación global, o usando otros métodos manualmente. Sin embargo, en este caso, tendrá que decirle a Selenium dónde colocó PhantomJS cada vez que ejecute Selenium:

PATH = "/ path / to / node_modules / phantomjs / bin: $ PATH" java -jar selenium-server-standalone-2.28.0.jar

Combinando todo

Ahora que tenemos todas las piezas, tenemos que poner todo junto..

Recuerde: antes de ejecutar cualquier prueba, debe ejecutar Selenium Server:

java -jar selenium-server-standalone-2.28.0.jar

Selenium ejecutará PhantomJS internamente; no tienes que preocuparte por eso.

Ahora, necesitamos conectarnos a Selenium desde nuestro JavaScript. Aquí hay un fragmento de muestra, que iniciará una conexión a Selenium y tendrá un objeto listo para controlar nuestra instancia de Selenium:

// Use webdriverjs para crear un cliente de Selenium var client = require ('webdriverjs'). Remote (desiredCapabilities: // Puede elegir otro navegador // http://code.google.com/p/selenium/wiki/ DesiredCapabilities browserName: 'phantomjs', // webdriverjs tiene una gran cantidad de resultados que generalmente son inútiles // Sin embargo, si algo sale mal, elimínelo para ver más detalles logLevel: 'silent'); client.init ();

Ahora, podemos describir nuestras pruebas y usar el cliente Variable para controlar el navegador. En la documentación está disponible una referencia completa para la API webdriverjs, pero aquí hay un breve ejemplo:

client.url ('http://example.com/') client.getTitle (function (title) console.log ('Title is', title);); client.setValue ('# field', 'value'); client.submitForm (); client.end ();

Usemos la sintaxis de Mocha y Chai para describir una prueba; probaremos algunas propiedades de la example.com página web:

describe ('Test example.com', function () before (function (done) client.init () .url ('http://example.com', done);); describe ('Check homepage' , function () it ('debería ver el título correcto', function (done) client.getTitle (function (title) expect (title) .to.have.string ('Dominio de ejemplo'); done (); );); it ('debería ver el cuerpo', function (done) client.getText ('p', function (p) expect (title) .to.have.string ('para ejemplos ilustrativos en documentos . '); done ();));); after (función (done) client.end (); done ();););

Es posible que desee compartir uno cliente Inicialización sobre muchos archivos de prueba. Cree un pequeño módulo Node para inicializarlo e importarlo en cada archivo de prueba:

cliente.js:

exports.client = require ('webdriverjs'). remote (// Settings;

test.js:

var client = require ('./ client'). client; var espera = requiere ('chai'). espera; // realizar pruebas

Corriendo

Las suites de prueba de Mocha se ejecutan con el moca binario. Si siguió esta guía e instaló Mocha localmente, debe describir una ruta completa al binario: node_modules / mocha / bin / mocha.

De forma predeterminada, Mocha trata cualquier prueba que demore más de dos segundos en fallar. Dado que en realidad estamos inicializando un navegador web y realizando una solicitud HTTP, debemos aumentar este tiempo de espera a 5 o 10 segundos:

node_modules / mocha / bin / mocha test.js -t 10000

Si todo salió según lo planeado, debería ver una salida como esta:

 . ✔ 1 prueba completa

Los siguientes pasos

Una vez que haya alcanzado los resultados deseados de pruebas funcionales, es posible que desee seguir mejorando su configuración..

Dos direcciones obvias son la integración continua y las pruebas de selenio distribuidas..

Integración continua

Tu objetivo debe ser minimizar el tiempo que pasas ejecutando pruebas.

Es posible que desee utilizar un servidor de integración continua automático completo, que ejecutará las pruebas cuando sea necesario automáticamente, y le informará si algo sale mal..

En el mundo del código abierto, el rol de un servidor de este tipo está cubierto por Jenkins CI: un servicio conveniente, potente y fácil de instalar, que ejecutará las pruebas cuando sea necesario, las ejecutará en cualquier configuración que proporcione y posiblemente ejecutará muchas más tareas relacionadas con la compilación, como implementar su código en servidores remotos.

Alternativamente, si te sientes aventurero, puedes experimentar con un nuevo proyecto, llamado GitLab CI, que ofrece menos funciones, pero se ve mejor y está integrado con GitLab, un clon autocontenido de GitHub..

En cualquier caso, su objetivo debe ser minimizar el tiempo que pasa ejecutando pruebas. En su lugar, las pruebas deben ejecutarse automáticamente y solo deben informarle si algo sale mal..

Rejilla de selenio

El selenio tiene una serie de limitaciones de implementación. Por ejemplo, no puede ejecutar más de unos pocos navegadores en la misma máquina para ser probado con Selenium.

Además, notará que, una vez que tenga muchas pruebas, ejecutarlas todas puede convertirse en un proceso largo. Aunque la integración continua alivia parcialmente este problema, es posible que aún desee realizar algunas pruebas en paralelo en diferentes máquinas.

Finalmente, pronto notará que desea probar diferentes navegadores en diferentes sistemas operativos. Y, aunque su código de prueba puede, en teoría, hablar con diferentes servidores Selenium, una vez que crezca un poco, esta configuración necesita centralización..

La configuración de Selenium Grid intenta proporcionar exactamente eso. En lugar de tener un servidor Selenium que controle varios navegadores en una máquina, tiene un servidor Selenium, que controla múltiples nodos Selenium, cada uno de los cuales controla solo algunos navegadores en un solo sistema operativo.


Conclusión

La pila resultante, aunque no trivial, en realidad, es bastante simple. La adición de PhantomJS al final de Selenium nos permite comenzar a utilizar Selenium sin mucha inversión inicial, como configurar servidores de prueba gráficos.

El uso de JavaScript como motor de prueba garantiza que nuestras pruebas se mantendrán relevantes en el contexto del desarrollo web en el futuro inmediato..