Garantizar la accesibilidad con pruebas automatizadas

En el mundo del desarrollo de software una funcionalidad que hoy funciona puede dejar de hacerlo mañana después de una modificación aparentemente inocente. Para evitar este problema se crean las pruebas automatizadas para mantener la funcionalidad y la forma de utilizar una interfaz de usuario.

La accesibilidad debería formar parte de esas pruebas para garantizar que todos los usuarios pueden acceder a la funcionalidad.

Sin embargo, todavía es frecuente tratarla como una actividad posterior al desarrollo. Primero se construye la interfaz, después se comprueba si funciona y, en algún momento, alguien ejecuta una herramienta de accesibilidad o realiza una auditoría. El problema de este planteamiento es que convierte la accesibilidad en una fotografía puntual cuando debería ser una propiedad del software que intentamos conservar durante toda su vida.

La automatización de las pruebas puede ayudar a garantizar y mantener esa accesibilidad.

Como explica Marcy Sutton en Writing Automated Tests for Accessibility, las pruebas automáticas no pueden descubrir todos los problemas de accesibilidad. Tampoco sustituyen las pruebas manuales ni las realizadas con personas con discapacidad. Su utilidad está en otro lugar: permiten comprobar de manera sistemática aquello que una máquina sí puede verificar y, sobre todo, detectar regresiones antes de que lleguen a producción.

La accesibilidad también puede sufrir regresiones

Una regresión aparece cuando una modificación introduce un problema en algo que anteriormente funcionaba.

Si una función debe devolver un determinado resultado para una entrada concreta, podemos escribir una prueba que establezca ese comportamiento. Cada vez que alguien modifique el código, la prueba volverá a ejecutarse.

Con la accesibilidad sucede exactamente lo mismo. Un botón puede tener hoy un nombre accesible y perderlo durante una refactorización. Un diálogo puede devolver correctamente el foco al elemento que lo abrió hasta que alguien modifica su implementación. Un componente de pestañas puede responder a las flechas del teclado y dejar de hacerlo después de actualizar una dependencia.

La interfaz puede parecer idéntica. Para una persona que utiliza el ratón puede incluso continuar funcionando con normalidad. Pero para otros usuarios el cambio puede haber roto una parte esencial de la aplicación.

Las pruebas automatizadas permiten convertir algunos de esos requisitos de accesibilidad en condiciones verificables. En lugar de confiar únicamente en que nadie elimine accidentalmente un comportamiento accesible, podemos hacer que el propio proyecto compruebe su existencia.

Automatizar no significa automatizarlo todo

La accesibilidad no puede reducirse a obtener un informe sin errores de una herramienta automática.

Una máquina puede comprobar determinadas propiedades del código y del documento. Puede encontrar ciertos usos incorrectos de ARIA, detectar algunos problemas de contraste, analizar etiquetas o identificar errores en la estructura HTML. También podemos escribir nuestras propias pruebas para comprobar el comportamiento de componentes concretos.

Pero existen preguntas mucho más difíciles.

¿Tiene sentido el orden de lectura? ¿Es comprensible el texto alternativo de una imagen dentro de su contexto? ¿Resulta sencillo completar una tarea utilizando un lector de pantalla? ¿Es predecible la gestión del foco? ¿Puede una persona comprender un mensaje de error y recuperarse de él?

No todas estas cuestiones pueden resolverse observando el DOM y aplicando un conjunto de reglas.

La automatización, por tanto, no debería entenderse como un sustituto de las pruebas de accesibilidad realizadas por personas. Es una capa adicional dentro de una estrategia más amplia.

Su ventaja consiste precisamente en encargarse de las comprobaciones repetibles para que el tiempo humano pueda dedicarse a aquello que exige interpretación, experiencia y contexto.

Probar resultados en lugar de implementaciones

Una buena prueba automatizada debería sobrevivir, dentro de lo razonable, a los cambios internos del software.
Las pruebas deberían concentrarse en el resultado esperado y no en los detalles de implementación.

Supongamos que tenemos un componente que muestra un diálogo. Desde el punto de vista de quien utiliza la interfaz, lo importante no es qué funciones internas se ejecutan ni qué variables cambian de valor. Lo que importa es que el diálogo pueda abrirse con el teclado, que el foco termine donde corresponde, que pueda cerrarse y que, al hacerlo, el usuario pueda continuar desde una posición coherente.

Una prueba demasiado vinculada a la implementación puede romperse cada vez que refactorizamos el componente, aunque su comportamiento siga siendo correcto. Cuando esto ocurre con frecuencia, las pruebas empiezan a percibirse como un obstáculo. Finalmente alguien las desactiva o las elimina.

Una prueba centrada en el comportamiento expresa algo diferente: mientras esta funcionalidad exista, esta propiedad debe seguir cumpliéndose.

En accesibilidad, esa diferencia es particularmente valiosa porque transforma ciertos requisitos en parte del contrato del componente.

El teclado como parte de las pruebas

El teclado es una de las herramientas más sencillas para comenzar a evaluar la accesibilidad de una interfaz.

Podemos recorrer una página utilizando la tecla Tab, comprobar si alcanzamos los controles interactivos, observar si el foco resulta visible y verificar si podemos realizar una tarea sin recurrir al ratón.

Una parte de ese comportamiento también puede incorporarse a las pruebas automatizadas.

Un diálogo puede tener una prueba que compruebe que Escape permite cerrarlo. Un menú puede verificar el funcionamiento de las teclas de dirección. Un componente de pestañas puede comprobar que el foco se desplaza de acuerdo con el patrón de interacción previsto.

Esto resulta especialmente interesante porque la accesibilidad deja de estar asociada únicamente al marcado HTML.

Un componente puede utilizar atributos ARIA aparentemente correctos y seguir siendo inaccesible si su comportamiento con el teclado es incorrecto. La accesibilidad de una interfaz dinámica depende tanto de la información que exponemos como de las interacciones que permitimos realizar.

Las pruebas de integración son especialmente adecuadas para muchas de estas comprobaciones, ya que el foco y la interacción suelen atravesar los límites de un único componente.

Pruebas unitarias y pruebas de integración

No todas las pruebas de accesibilidad tienen que ejecutarse al mismo nivel.

Una prueba unitaria puede comprobar una pieza aislada del sistema. Por ejemplo, que determinada propiedad proporcionada a un componente termine convirtiéndose en el nombre accesible de un botón.

Este tipo de prueba es rápida y permite verificar problemas concretos.

Las pruebas de integración permiten observar un escenario más amplio. Podemos cargar una interfaz, simular una interacción con el teclado y comprobar qué elemento recibe el foco después de una determinada acción.

Las pruebas de extremo a extremo llevan esta idea todavía más lejos, reproduciendo recorridos próximos a los de una persona que utiliza la aplicación.

No existe un único nivel correcto para probar la accesibilidad. La elección depende de aquello que queremos garantizar.

Si nos interesa comprobar que una API transmite correctamente determinada información de accesibilidad, una prueba unitaria puede ser suficiente. Si queremos saber qué sucede con el foco después de abrir y cerrar varios componentes, necesitaremos observar una porción mayor de la aplicación.

Incorporar motores de accesibilidad

Además de escribir pruebas específicas para nuestros componentes, podemos incorporar motores especializados en detectar automáticamente problemas de accesibilidad.

Uno de los más conocidos es axe-core, desarrollado por Deque. Puede integrarse con distintos entornos de pruebas para analizar un componente, una página o un estado determinado de la aplicación.

La idea es sencilla. La prueba presenta una interfaz al motor de accesibilidad, ejecuta el análisis y comprueba los resultados obtenidos. Si aparecen determinadas infracciones, la prueba puede fallar.

Esto permite trasladar algunas comprobaciones al mismo lugar en el que ya verificamos el resto del software.

En lugar de esperar a una auditoría posterior, una modificación que introduzca ciertos errores puede provocar un fallo durante la integración continua. El problema aparece entonces mucho más cerca del momento en que fue introducido.

Esta proximidad tiene una ventaja práctica considerable. Corregir un error cuando todavía estamos trabajando en el componente suele ser más sencillo que descubrirlo semanas después, cuando el código ya se encuentra integrado con otras partes del sistema.

Probar los estados, no solamente las páginas

Las aplicaciones web modernas cambian constantemente de estado. Un menú cerrado no contiene necesariamente los mismos elementos visibles que un menú abierto. Un diálogo puede no existir en el DOM hasta que alguien pulsa un botón. Un formulario puede mostrar mensajes adicionales después de una validación. Un acordeón oculta información hasta que se expande.

Todo esto plantea un problema para las herramientas automáticas: solo pueden analizar aquello que existe en el estado que les presentamos.
Ejecutar un análisis de accesibilidad inmediatamente después de cargar una página puede dejar fuera una parte considerable de la interfaz.

Por esta razón las pruebas automáticas deberían recorrer los estados significativos.

Podemos analizar la página inicialmente, abrir después un diálogo y volver a analizarla. Podemos desplegar un menú, provocar los errores de un formulario o mostrar contenido que inicialmente estaba oculto.

La unidad de accesibilidad que nos interesa comprobar no siempre es la página. En una aplicación dinámica, muchas veces es el estado de la interfaz.

Accesibilidad dentro de la integración continua

Cuando estas pruebas forman parte de la ejecución habitual del proyecto, la accesibilidad entra también en el proceso de integración continua.

Una auditoría periódica nos dice qué problemas existen en un momento determinado. Una prueba automática puede impedir que ciertos problemas conocidos vuelvan a introducirse.

La diferencia es parecida a la que existe entre inspeccionar periódicamente si una puerta permanece cerrada e instalar un mecanismo que avise cada vez que alguien la deja abierta.

La segunda opción tampoco garantiza que el edificio sea seguro. Pero convierte una condición concreta en algo que se vigila continuamente.

Con la accesibilidad podemos hacer lo mismo. No podremos automatizar toda la experiencia de una persona, pero sí establecer determinadas condiciones que el software no debería incumplir.

El peligro de confiar demasiado en el resultado

Existe una consecuencia incómoda al automatizar la accesibilidad que consiste en que podemos empezar a confiar demasiado en aquello que hemos automatizado.

Una batería de pruebas sin errores no demuestra que un producto sea accesible. Más bien demuestra que ha superado las comprobaciones que hemos decidido ejecutar.

Las herramientas automáticas trabajan con reglas que pueden evaluarse mediante software. La experiencia de una persona utilizando una interfaz es considerablemente más compleja. Un sitio puede superar todas las comprobaciones automáticas y continuar presentando obstáculos importantes. Por esta razón las pruebas manuales siguen siendo necesarias.

Utilizar únicamente el teclado, probar con lectores de pantalla, comprobar diferentes niveles de ampliación, observar el comportamiento en dispositivos móviles y estudiar la experiencia con distintas tecnologías de apoyo permiten encontrar problemas que difícilmente aparecerán en una comprobación automática.

Además de todo esto deberíamos probar con personas.

Se puede comprobar técnicamente que un componente sigue un patrón accesible y descubrir después que resulta confuso durante una tarea real. Cumplimiento técnico y usabilidad están relacionados, pero no son equivalentes.

Automatizar para reservar tiempo para las personas

El objetivo final de automatizar las pruebas de accesibilidad no debería ser eliminar la intervención humana, sino utilizarla mejor.

Hay comprobaciones que una máquina puede repetir cientos de veces con un coste muy pequeño. No tiene demasiado sentido pedir a una persona que las realice manualmente en cada modificación si podemos convertirlas en pruebas fiables.

Ese tiempo puede dedicarse a cuestiones que necesitan criterio humano.

La automatización también proporciona una memoria que los equipos de desarrollo no siempre tienen. Las personas cambian de proyecto, los componentes evolucionan y las decisiones tomadas meses atrás pueden olvidarse. Una prueba permanece junto al código recordando que determinado comportamiento no es accidental.

Si alguien implementó correctamente la gestión del foco de un diálogo, una prueba puede conservar esa decisión mucho después de que se haya olvidado la conversación que la originó.

La accesibilidad como propiedad del software

Cuando escribimos una prueba para una característica de accesibilidad estamos diciendo que ese comportamiento forma parte del producto.
No es una mejora opcional que comprobaremos al final. No es una característica externa al código. Es una condición que esperamos que siga siendo cierta después de cada modificación.

La automatización no puede decirnos que una aplicación es accesible. Tampoco puede sustituir a una persona utilizando un lector de pantalla, navegando con el teclado o intentando completar una tarea real.

Lo que si puede hacer es impedir que olvidemos automáticamente algunas de las cosas que ya habíamos aprendido a hacer bien.

Una estrategia madura de accesibilidad combina esas capas. Automatiza aquello que puede expresarse mediante reglas y comportamientos verificables, utiliza pruebas manuales para explorar lo que necesita interpretación y recurre a personas con discapacidad para conocer la experiencia que ningún conjunto de aserciones puede reproducir.

Las pruebas automatizadas no son el destino de la accesibilidad. Son una forma de evitar que, mientras avanzamos, deshagamos parte del camino recorrido.

Deja una respuesta

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

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.