Last Updated: 2019-08-31
Los navegadores son aplicaciones cuya principal función es permitir el acceso a contenido web al consultar información de servidores en internet (por medio de varios protocolos) y renderizar contenido mixto en una interfaz gráfica. Las aplicaciones web existen en función de estos navegadores, ya que son la principal plataforma de interacción para ellas y, por ende, representan un objetivo importante al momento de hacer pruebas automáticas sobre este tipo de aplicaciones.
Teniendo en cuenta lo anterior, es apenas natural hacer pruebas E2E para validar el comportamiento de las aplicaciones web. Esto se hace por medio de herramientas como Puppeteer, que automatizan la interacción con los navegadores web por medio de comandos escritos en un lenguaje de programación convencional. De esta forma es posible explorar la totalidad de las aplicaciones web que desee probar.
Puppeteer es una librería lanzada en 2017 que brinda un API para automatizar el navegador de Chromium o Chrome. Esta brinda la posibilidad de ejecutar varias funcionalidades sobre una aplicación web de forma automática al manipular un clon del navegador. Está disponible únicamente para Node.js y soporta la mayoría de las interacciones y modificaciones sobre los navegadores más recientes. Este proyecto es mantenido por el equipo de Chrome DevTools.
Al final de este tutorial usted tendrá:
Al desarrollar este tutorial usted aprenderá:
Puppeteer es un proyecto de código abierto. Este se aloja en un repositorio público de GitHub al cual puede acceder en el siguiente enlace: https://github.com/puppeteer/puppeteer. Se sugiere que lea la documentación presente en el archivo Readme.md de este repositorio para comprender todos los detalles necesarios para automatizar cada aspecto posible de un navegador.
Como se indica en la documentación oficial, Puppeteer es un API que permite automatizar Chromium y Chrome por medio del protocolo de sus DevTools. Desde el momento de instalación de la dependencia, se descarga un archivo binario conteniendo una versión ligera del navegador Chromium que permite su ejecución en modo headless.
Las funciones del API de Puppeteer son asíncronas, y los programas que le utilizan típicamente parten de una función flecha asíncrona sin nombre que se llama a sí misma, de la forma (async ()=>{//code})();
. El API de Puppeteer permite trabajar con dos objetos principales para la automatización de los navegadores, que son Browser
y Page
. El primero contiene una de las instancias de los navegadores mencionados, y el segundo permite abstraer una página web, por lo cual será fundamental para referirse a la interfaz de la aplicación web e interactuar con acciones básicas.
Puppeteer brinda soporte para el comportamiento de las aplicaciones web cotidianas y permite realizar las interacciones que un usuario tendría normalmente por medio de un navegador. Entre otras, permite explorar una Single Page Application y generar contenido pre-renderizado con SSR, automatizar entradas para llenar formularios, probar interfaz, entre otros. También permite crear capturas de pantalla en formato de imagen o .pdf
.
Además de esto, Puppeteer destaca por su integración con herramientas nativas propias de Chromium y las herramientas de desarrollo provistas en Chrome. En particular, con Puppeteer se puede probar el uso de extensiones de Chrome y su interacción con las aplicaciones web, realizar capturas del desempeño de la aplicación para diagnosticar problemas de rendimiento, depurar las pruebas, y probar las funcionalidades más recientes de las versiones actualizadas de Chrome.
Para el caso de este tutorial se harán pruebas para verificar la correcta funcionalidad de una sencilla página web construida en Angular, cuya única funcionalidad es permitir el registro, inicio de sesión y visualización de los usuarios creados.
Ingrese al siguiente enlace para conocer la aplicación en cuestión: https://angular-6-registration-login-example.stackblitz.io/register. Interactúe con los botones "Register" y "Cancel" y luego proceda a llenar el formulario de registro. Verá que ahora será redirigido a la página de login, pero tendrá un mensaje adicional indicando el éxito de la operación de registro. Ingrese ahora con las credenciales que recién registró y podrá ver una página con su nombre de usuario.
El flujo estándar de esta aplicación debería ser como el de la siguiente imagen:
Imagen 1. Flujo de vistas de la aplicación web
Sin embargo, usted podrá notar que existen ciertos detalles que pueden variar según las condiciones del escenario.
Para el caso de este tutorial, basta con que aprenda a hacer operaciones básicas en su prueba como abrir URLs, hacer clics, llenar campos de texto y consultar la presencia de determinados elementos gráficos. En particular, se espera construir una prueba que haga lo siguiente:
En primer lugar, debe asegurarse de crear un proyecto haciendo uso de Node.js para poder crear y ejecutar la prueba con Puppeteer. Para esto, abra una terminal y ubíquese en un directorio vacío donde vaya a ubicar el proyecto de este tutorial. Una vez allí ejecute el siguiente comando:
npm init -y
De esta forma, habrá inicializado un proyecto de Node.js. Podrá ver que en su directorio se creó un archivo package.json
con valores por defecto (a causa del flag -y). Ahora podrá instalar las dependencias necesarias en este proyecto.
Actualmente su proyecto de Node.js únicamente contiene un archivo con metadatos del proyecto, pero no cuenta con los archivos a ejecutar ni con las dependencias necesarias. Para instalar y utilizar Puppeteer en sus pruebas, debe instalar el paquete de npm con el siguiente comando:
npm install puppeteer
Esto agregará las líneas necesarias a su archivo package.json
para declarar Puppeteer como dependencia del proyecto, creará un archivo package-lock.json
e instalará Puppeteer en el directorio node_modules
.
Como está declarado en su archivo package.json
, el punto de entrada de su aplicación será el archivo index.js
, ubicado en el directorio del proyecto. Cree dicho archivo e inicialmente agregue el siguiente contenido para tener la estructura básica de un programa de Puppeteer:
const puppeteer = require('puppeteer'); (async()=>{ const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://angular-6-registration-login-example.stackblitz.io/register'); await new Promise(r => setTimeout(r, 7000)); await page.screenshot({path: './pagina.png'}) await page.click('button') await new Promise(r => setTimeout(r, 9000)); await page.screenshot({path: './pagina2.png'}) console.log('Project loaded') //Interactuar con la aplicación web //... await browser.close(); return; })().catch(e=>console.log(e));
En este archivo ya podrá incluir las instrucciones particulares de la prueba que se planteó previamente en este tutorial. En primer lugar, debe cambiar el valor de la constante url
por ‘https://angular-6-registration-login-example.stackblitz.io/register'. Opcionalmente, también puede eliminar dos de los navegadores del arreglo para realizar la prueba una única vez.
Recuerde el listado de acciones del paso anterior del tutorial. Las verificaciones que se mencionaron las hará por medio de llamados a la función console.log
.
Ahora, en este mismo archivo, debe agregar las instrucciones que le permiten interactuar con los elementos correspondientes. En la sección de su archivo que contiene los comentarios "Interactuar con la aplicación web" y "...", debe agregar las siguientes instrucciones:
await page.click('a.btn.btn-link') console.log(`Clicked "cancel". URL is now ${page.url()}`) await page.click('a.btn.btn-link') console.log(`Clicked "register". URL is now ${page.url()}`) await page.click('button.btn.btn-primary') let feedback = await page.$$('div.invalid-feedback'); let elems=0 for(let i of feedback){elems++} await page.screenshot({path:'./form-feedback.png'}) console.log(`Clicked "Register" with an empty form. Feedback is shown in ${elems} elements`) await page.type('input[formcontrolname="firstName"]', 'Monitor'); await page.type('input[formcontrolname="lastName"]', 'Pruebas'); await page.type('input[formcontrolname="username"]', 'pruebas'); await page.type('input[formcontrolname="password"]', 'MISO4208'); await page.click('button.btn.btn-primary') await new Promise(r => setTimeout(r, 7000)); await page.screenshot({path:'./success-feedback.png'}) feedback = await page.$("div.alert.alert-success") let text = await page.evaluate(el => el.textContent, feedback) console.log(`Success dialog after creating user with message: ${text}`) await page.type('input[formcontrolname="username"]', 'pruebas'); await page.type('input[formcontrolname="password"]', 'MISO4208'); await page.click('button.btn.btn-primary') await new Promise(r => setTimeout(r, 7000)); feedback = await page.$('h1'); text = await page.evaluate(el => el.textContent, feedback) await page.screenshot({path:'./after-login.png'}) console.log(`Logged in. Your user was ${text==='Hi Monitor!'?'successfully':'not'} created`)
Lea el código e identifique qué instrucciones corresponden a las acciones de la prueba que se enunciaron en el paso anterior. Podrá notar que en varios momentos se toma una captura de pantalla, la cual se almacena en el directorio raíz (no obstante, este directorio se puede cambiar con el path indicado). Así mismo, podrá notar que en ciertos momentos se agregaron tiempos de espera de forma manual con la instrucción await new Promise(r => setTimeout(r, 7000))
, esto se debe a que el comportamiento de esta página web, como el de varias SPA desarrolladas en Angular, es diferente al flujo tradicional y, por ende, maneja de forma distinta los eventos del navegador.
Para ejecutar el escenario, es necesario que haya guardado el archivo anterior. Desde una terminal, ubíquese en el directorio raíz del proyecto de npm que creó, y ejecute el comando node index.js
, el cual corre el contenido de su archivo index.js
con el motor de Node.js.
En primer lugar, al ejecutar la prueba podrá ver en su terminal los registros que se escribieron manualmente con las instrucciones console.log. Estos fueron incluidos según las acciones que comprenden la prueba, las cuales se listaron en un paso anterior. Por sí solo, Puppeteer no ofrece ninguna funcionalidad de reportes o registros de la prueba, así que es necesario incluirla dentro de todas las pruebas. Por otro lado, Puppeteer sí ofrece la posibilidad de generar imágenes o archivos .pdf con las capturas de pantalla de la página web en cierto momento.
En el caso de esta prueba también se incluyeron instrucciones page.screenshot para generar estas imágenes. Desde un explorador de archivos podrá ver las imágenes generadas en el directorio raíz, las cuales deben contener los archivos de la siguiente imagen:
Imagen 2. Imágenes generadas en la prueba
Notará que las imágenes muestran las vistas más importantes del recorrido que usted hizo de forma manual mientras exploraba la página. Estas imágenes podrá utilizarlas luego de la forma que lo requiera.
¡Felicidades!
Al finalizar este tutorial, usted pudo familiarizarse con el proceso requerido para probar funcionalidades de una página web haciendo uso de Puppeteer.
Ahora usted podrá crear sus propios scripts de prueba para explorar las funcionalidades de otras aplicaciones web con la misma estrategia de este tutorial.
Juan Sebastián Espitia Acero | Autor |
Norma Rocio Héndez Puerto | Revisora |
Mario Linares Vásquez | Revisor |