Last Updated: 2020-05-05
Las pruebas de regresión visual consisten en pruebas que se realizan sobre la interfaz gráfica de una aplicación y se fundamentan en la comparación de elementos gráficos representados como imágenes. Es decir, estas pruebas permiten ver diferencias entre varias imágenes al realizar una comparación de todos los píxeles de cada una de ellas.
No requieren una integración con la aplicación en cuestión dado que el único insumo necesario para llevarlas a cabo es la interfaz gráfica de una aplicación e incluso, en ocasiones, únicamente las imágenes. Esto facilita que la ejecución de dichas pruebas se realice de forma paralela con el desarrollo.
Uno de los principales objetivos de las pruebas de regresión visual consiste en realizar comparaciones de las versiones de la interfaz gráfica para hallar el impacto que pueden tener ciertos cambios en el código del proyecto. Como su nombre lo indica, se busca hacer una regresión sobre los componentes visuales de la interfaz para llevar un rastro de los avances.
Otro de los objetivos más importantes es encontrar problemas que puedan surgir en la interfaz gráfica. Estos problemas pueden corresponder a múltiples ámbitos como, por ejemplo, la similaridad entre la interfaz propuesta en la etapa de diseño de UI y la interfaz que se ha ido desarrollando, la superposición entre componentes de la vista, la posición o tamaño relativo de componentes, o la adaptación de la interfaz gráfica ante los cambios en el tamaño del viewport, la orientación o tamaño de la pantalla. Este tipo de bugs visuales puede ser detectado con rapidez por medio de estas pruebas.
No obstante, este tipo de pruebas tiene una limitación en términos de su automatización, pues requiere que algunas etapas tengan intervención de un humano para definir si los hallazgos de estas pruebas corresponden a problemas de interfaz. Los resultados de la prueba deben ser interpretados, ya que establecer criterios de aceptación de forma automática no asegura que sean adecuadamente catalogadas como correctas o incorrectas. Esto es porque las pruebas suelen ser muy precisas y el margen de aceptación, o tolerancia, sea más flexible y difícil de determinar por parte del grupo de trabajo.
Al desarrollar este tutorial aprenderá:
En este caso se partirá de una aplicación web como base, por lo cual los aprendizajes respectivos al desarrollo de esta no se incluyen como parte del tutorial.
En el tutorial se dará una serie de instrucciones que le permitirán desplegar una aplicación web de prueba y, sobre ella, realizar pruebas de regresión visual. Al final del tutorial usted deberá tener:
Para el caso de este tutorial se hará uso de una aplicación web sencilla que permite generar paletas de colores aleatorias que pueden usarse dentro de las reglas CSS de otra página web. Se decidió que la paleta de colores incluyera únicamente 5 colores complementarios (o equidistantes) entre ellos, cuya generación se realiza de forma aleatoria usando un esquema de generación que consiste en variar la tonalidad de los colores en la escala HSB/HSV.
En esta escala de colores, la tonalidad (hue), representada en la H puede tomar valores entre 0 y 359, que representan los grados en el círculo cromático. La saturación y el brillo, representadas en la S y la B respectivamente, toman valores entre 0 y 1 para representar un porcentaje.
Así, la aplicación selecciona una tonalidad aleatoria y calcula las otras 4 que serían equidistantes en este círculo al sumar una cantidad igual de 360/5 grados (es decir, 72) para cada uno y normalizar el valor a la escala aceptada. Estos colores se muestran en la sección superior de la página web y las reglas CSS que los contienen se muestran en un textarea
de la sección inferior.
La versión base de la aplicación web se encuentra alojada en GitHub Pages en el siguiente enlace: https://monitor177.github.io/color-palette/. Así mismo, el código fuente se encuentra alojado en el repositorio de GitHub del siguiente enlace: https://github.com/monitor177/color-palette/.
Usted usará la aplicación base como una referencia de la interfaz y comparará esta aplicación con su propio despliegue. Antes de interactuar con la aplicación original, ingrese al enlace del repositorio y revise el código del proyecto alojado en el repositorio. Podrá ver la implementación de los esquemas de generación de la paleta de color mencionados en el apartado anterior.
Una vez termine de comprender el funcionamiento de la aplicación, cree un fork del repositorio haciendo clic en el botón correspondiente de la sección superior del repositorio, el cual se muestra en la siguiente imagen:
Imagen 1. Sección superior del repositorio con botón "Fork"
Al hacer clic en este botón, GitHub le redirigirá a su versión del repositorio. Desde allí, ingrese a la pestaña "Settings", la cual se muestra en la siguiente imagen:
Imagen 2. Pestaña "Settings" del repositorio nuevo
En las configuraciones del repositorio, diríjase a la sección titulada "GitHub Pages". Desde allí va a configurar su repositorio para que despliegue la aplicación contenida en el código fuente como un sitio web estático alojado en GitHub Pages. Haga clic en el botón desplegable que hace referencia a la fuente en la sección "Source" y con el texto "None", el cual se muestra en la siguiente imagen:
Imagen 3. Sección de GitHub Pages para elegir la fuente del código
Este botón mostrará varias opciones para alimentar el código del sitio web estático. Elija la primera, llamada "master branch" para desplegar una página web a partir del código que se encuentra en la rama principal del repositorio. Podrá ver un mensaje de confirmación como el de la imagen a continuación, el cual indica un despliegue exitoso y contiene la dirección URL donde se encuentra la aplicación.
Ingrese a la URL del sitio web de referencia en el siguiente enlace: https://monitor177.github.io/color-palette/. Explore rápidamente los elementos de la interfaz y genere varias paletas de colores con los botones de la parte inferior para ver ejemplos de colores aleatorios que pueden surgir con este esquema de generación. Las interacciones de la aplicación son limitadas y podrían resumirse en el siguiente gif:
Imagen 4. Interacción de ejemplo con la aplicación web
Para familiarizarse con las pruebas de regresión visual, usted hará comparaciones entre varios aspectos visuales de la misma interfaz gráfica. La aplicación que se eligió permite tener variaciones inesperadas pero predecibles sobre la interfaz y, por ende, le permitirán comprender las particularidades de las herramientas de regresión.
El paso inicial de la prueba debe ser el de acceder a la URL donde se aloja la página web haciendo uso de una herramienta que simule o se base en el comportamiento de un navegador. Es importante tener en cuenta el viewport o tamaño de la ventana del navegador para poder comparar con otras imágenes de la interfaz que manejen la misma escala.
Esta herramienta debe capturar una imagen que muestre el aspecto de la interfaz de la aplicación. Esta captura será tomada como el punto de referencia y comparación ante los cambios durante la prueba.
Tal como usted probablemente lo hizo al momento de interactuar con la aplicación, el siguiente paso consiste en hacer clic en el botón de generar una paleta de colores para inducir un cambio en el aspecto visual de la interfaz. Cuando este cambio surta efecto, se debe capturar una imagen que muestre el aspecto modificado de la interfaz. Esta captura podrá compararse ahora con la imagen de referencia para detallar las diferencias gráficas y esta comparación podrá ser luego interpretada por el evaluador de la prueba (usted).
Resemble.js es una herramienta que permite realizar análisis visual sobre imágenes haciendo uso de JavaScript y HTML. Esta se distribuye como una librería de Node.js, permite extraer información sobre una imagen y también realizar comparaciones entre imágenes. Para conocer el detalle del API, diríjase a la documentación en el siguiente enlace: https://github.com/rsmbl/Resemble.js/blob/master/README.md.
Para comenzar, cree un proyecto de Node.js donde alojará el código para ejecutar la prueba de regresión. Para esto, abra una terminal en su máquina y ubíquese en un directorio donde vaya a ubicar el proyecto con el comando cd <ruta>
. Cree un subdirectorio vacío con el comando mkdir <nombre>
y ubíquese en él.
Una vez allí, cree un proyecto con el comando npm init
. Este comando le solicitará cierta información para crear el archivo package.json
como la de la siguiente imagen:
Imagen 5. Campos de entrada para la creación del package.json
En principio, esta información no influye en la construcción del proyecto y únicamente se utiliza para el archivo JSON de configuración del proyecto. Ahora podrá incluir los archivos que necesite para ejecutar la aplicación e instalar sus dependencias.
En este directorio del proyecto debe crear un archivo llamado index.js
que contendrá el código fuente para realizar la prueba de regresión visual y un archivo config.json
que le permitirá establecer los parámetros requeridos para la prueba.
En el archivo index.js deberá incluir el siguiente código fuente:
const playwright = require('playwright');
const compareImages = require("resemblejs/compareImages")
const config = require("./config.json");
const fs = require('fs');
const { viewportHeight, viewportWidth, browsers, options } = config;
async function executeTest(){
if(browsers.length === 0){
return;
}
let resultInfo = {}
let datetime = new Date().toISOString().replace(/:/g,".");
for(b of browsers){
if(!b in ['chromium', 'webkit', 'firefox']){
return;
}
if (!fs.existsSync(`./results/${datetime}`)){
fs.mkdirSync(`./results/${datetime}`, { recursive: true });
}
//Launch the current browser context
const browser = await playwright[b].launch({headless: true, viewport: {width:viewportWidth, height:viewportHeight}});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto(config.url);
await page.screenshot({ path: `./results/${datetime}/before-${b}.png` });
await page.click('#generate');
await page.screenshot({ path: `./results/${datetime}/after-${b}.png` });
await browser.close();
const data = await compareImages(
fs.readFileSync(`./results/${datetime}/before-${b}.png`),
fs.readFileSync(`./results/${datetime}/after-${b}.png`),
options
);
resultInfo[b] = {
isSameDimensions: data.isSameDimensions,
dimensionDifference: data.dimensionDifference,
rawMisMatchPercentage: data.rawMisMatchPercentage,
misMatchPercentage: data.misMatchPercentage,
diffBounds: data.diffBounds,
analysisTime: data.analysisTime
}
fs.writeFileSync(`./results/${datetime}/compare-${b}.png`, data.getBuffer());
}
console.log('------------------------------------------------------------------------------------')
console.log("Execution finished. Check the report under the results folder")
return resultInfo;
}
(async ()=>console.log(await executeTest()))();
Este código contiene una sección para importar las dependencias y los parámetros de la configuración; seguida de una función que contiene la ejecución principal, donde se leen los navegadores en los que debe ejecutarse la prueba; luego se crea un directorio para las imágenes y se procede a acceder a la aplicación web desde cada navegador para luego capturar la pantalla inicial, crear una paleta de colores y capturar la pantalla luego de los cambios. Una vez se tienen ambas capturas, se realiza una comparación con Resemble.js, se almacena la imagen generada por esta y se muestra la metainformación obtenida en la comparación.
En cuanto al archivo config.json, incluya la siguiente información en él:
{
"url":"https://monitor177.github.io/color-palette/",
"browsers":["chromium", "webkit", "firefox"],
"options":{
"output": {
"errorColor": {
"red": 255,
"green": 0,
"blue": 255
},
"errorType": "movement",
"largeImageThreshold": 1200,
"useCrossOrigin": false,
"outputDiff": true
},
"scaleToSameSize": true,
"ignore": "antialiasing"
},
"viewportHeight":600,
"viewportWidth":800
}
Note que la información incluida corresponde a la dirección URL de la página que probará, los navegadores que utilizará Playwright para comparar imágenes, los tamaños del viewport y la configuración de Resemble.js. Entre la configuración de Resemble.js podrá ver que se define un color para marcar las diferencias en las imágenes, un tipo de error que detecta el movimiento de posición como diferencia relevante, un umbral para limitar el tamaño de las imágenes, un indicador para utilizar Cross-Origin para obtener las imágenes, un indicador para marcar las diferencias, un indicador para ajustar las imágenes al mismo tamaño y una opción para ignorar cierto tipo de diferencias como el antialiasing (que puede variar según las resoluciones de pantalla).
Para poder ejecutar la prueba, el proyecto requiere varias librerías que son Playwright, para controlar y poder realizar pruebas sobre la aplicación web simulando el comportamiento de navegadores web; fs para manejar archivos de forma local, y la funcionalidad compareImages
de Resemble.js para comparar las imágenes de la interfaz.
Para instalar Playwright, ejecute el siguiente comando:
npm install playwright
Esta librería puede tomar un tiempo en instalar dado que requiere obtener instancias de tres navegadores diferentes y estos exigen un tamaño importante.
Para instalar Resemble.js ejecute el siguiente comando:
npm install resemblejs
La librería fs no requiere instalación por medio de comando.
Esto incluirá las dependencias dentro de sus archivos package.json
y package-lock.json
para futura configuración y descargará las librerías mencionadas en la carpeta node_modules
para ser usadas dentro del proyecto.
Como vio en el código fuente, la prueba genera varios archivos como resultado, que son imágenes de las capturas de pantalla y otras imágenes de comparación. En este momento usted puede ejecutar el archivo index.js haciendo uso de Node.js y comprobar que los resultados de la prueba salgan de forma adecuada. Para esto, ejecute el siguiente comando desde una terminal ubicada en el directorio de su proyecto:
node index.js
Luego de un tiempo, podrá ver que la consola le indica que la prueba terminó con un mensaje que dice "Execution finished. Check the report under the results folder". Ahora, desde el explorador de archivos podrá ver que se creó una nueva carpeta llamada results. Al abrirla, se encontrará con otro directorio cuyo nombre corresponde a la fecha y hora del momento en que ejecutó la prueba. Dentro de este directorio podrá ver las imágenes mencionadas anteriormente, como se puede ver en la siguiente imagen:
Imagen 6. Imágenes resultantes después de ejecutar la prueba
Podrá notar una imagen con el prefijo before, una con el prefijo after y otra con el prefijo compare para cada uno de los navegadores definidos en el archivo config.json
. Explore las imágenes e intente buscar diferencias relevantes. Luego, note cómo en los archivos compare-<browser>.png
se marcan las diferencias entre las imágenes before y after con diferentes tonalidades del color que se definió también en el archivo config.json
.
Ahora que conoce las precondiciones y postcondiciones de la prueba, usted debe utilizar estos insumos para crear un reporte que muestre de forma fácil y adecuada los resultados de la prueba de regresión visual. Para esto, en su archivo index.js debe incluir varias instrucciones que permitirán la creación de reportes. Abra el archivo y agregue al final del mismo las siguientes funciones:
function browser(b, info){
return `<div class=" browser" id="test0">
<div class=" btitle">
<h2>Browser: ${b}</h2>
<p>Data: ${JSON.stringify(info)}</p>
</div>
<div class="imgline">
<div class="imgcontainer">
<span class="imgname">Reference</span>
<img class="img2" src="before-${b}.png" id="refImage" label="Reference">
</div>
<div class="imgcontainer">
<span class="imgname">Test</span>
<img class="img2" src="after-${b}.png" id="testImage" label="Test">
</div>
</div>
<div class="imgline">
<div class="imgcontainer">
<span class="imgname">Diff</span>
<img class="imgfull" src="./compare-${b}.png" id="diffImage" label="Diff">
</div>
</div>
</div>`
}
function createReport(datetime, resInfo){
return `
<html>
<head>
<title> VRT Report </title>
<link href="index.css" type="text/css" rel="stylesheet">
</head>
<body>
<h1>Report for
<a href="${config.url}"> ${config.url}</a>
</h1>
<p>Executed: ${datetime}</p>
<div id="visualizer">
${config.browsers.map(b=>browser(b, resInfo[b]))}
</div>
</body>
</html>`
}
Adicionalmente, en la función executeTest que se ejecuta como función principal, incluya la escritura de este archivo en el directorio que contiene el reporte para la ejecución actual. Para esto, justo después de que finaliza el ciclo for que recorre los browsers (linea 47), escriba las siguientes instrucciones para copiar el archivo index.css
a cada reporte y para crear el archivo HTML del reporte:
for(b of browsers){
...
}
fs.writeFileSync(`./results/${datetime}/report.html`, createReport(datetime, resultInfo));
fs.copyFileSync('./index.css', `./results/${datetime}/index.css`);
Su código ahora genera un archivo report.html
para cada ejecución. Sin embargo, los componentes de este reporte dependen de una hoja de estilos que aún no existe. Cree un archivo llamado index.css
en el directorio del proyecto e incluya las siguientes reglas de estilo:
.browser {
position: relative;
margin: 5px auto;
padding: 10px 30px;
background-color: #FAFAFA;
box-shadow: 0 3px 6px 0 rgba(0,0,0,0.16);
min-height: 40px;
-webkit-break-inside: avoid;
break-inside: avoid;
}
.btitle {
padding: 5px 0;
}
.imgline {
position: relative;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.imgcontainer {
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
padding: 0 25px;
padding-top: 20px;
text-align: center;
}
.imgname {
text-align: center;
font-family: latoregular;
color: #787878;
display: block;
margin: 0 auto;
text-transform: uppercase;
padding: 5px 0;
padding-bottom: 15px;
font-size: 12px;
}
.img2 {
width: auto;
max-width: 100%;
max-height: 400px;
}
.imgfull{
width:100%
}
Una vez haya creado este archivo, se copiará a la carpeta respectiva de cada ejecución con las líneas de código que agregó.
Vuelva a ejecutar la prueba con el comando node index.js
y revise los contenidos del reporte más reciente. Abra el archivo index.html
. Ahora podrá ver un reporte sencillo como el que se muestra en la siguiente imagen:
Imagen 7. Reporte generado con información de Resemble y Playwright
Como lo pudo notar, las pruebas de regresión visual son bastante rápidas y se basan en principios sencillos. Haciendo uso de herramientas especializadas en análisis de imágenes se puede efectuar comparaciones entre imágenes y hallar diferencias detalladas con un buen nivel de exactitud; a partir de estas comparaciones un evaluador de la prueba puede determinar si los cambios en la interfaz gráfica son significativos y representan un impacto negativo sobre la calidad de la aplicación.
El proceso para ejecutar la prueba puede variar un poco según la herramienta que se esté utilizando, pero la intención se mantiene y es hallar diferencias visuales. En los reportes generados, puede ver que la comparación entre las imágenes se basa en capturar las diferencias de los pixeles de las posiciones equivalentes y mostrarlas en una sola imagen.
En el caso de Backstop.js, la herramienta integra la comparación de imágenes con el manejo de escenarios y su ejecución en un navegador, de tal forma que los reportes son generados de forma automática en un formato sólido de HTML. No obstante, esto puede limitar el alcance, dado que se basa en Puppeteer, la cual es una librería que permite automatizar los navegadores de Chrome únicamente.
Es importante resaltar que los porcentajes de diferencia calculados no son absolutos y pueden variar según la herramienta y los parámetros que se eligen para la función.
¡Felicidades!
Al completar este tutorial usted pudo familiarizarse mejor con las pruebas de regresión visual.
Ahora conoce y maneja una herramienta de JavaScript que le permiten comparar su interfaz gráfica en distintos momentos para rastrear cambios o detectar errores, y podrá utilizarla para realizar pruebas de regresión visual sobre otras de sus aplicaciones web.
Juan Sebastián Espitia Acero | Autor |
Norma Rocio Héndez Puerto | Revisora |
Mario Linares Vásquez | Revisor |