wandres.dev
PROTOCOLO Y AUTOMATIZACIÓN · CDP y Puppeteer

La grabadora: capturar un flujo de usuario y reproducirlo

Grabar una secuencia de interacciones, cómo se eligen los selectores, editar los pasos y las aserciones, y reproducir midiendo el rendimiento de cada paso.

⏱ 17 min

El panel de grabadora registra lo que haces en la página como una secuencia de pasos estructurados, la reproduce cuantas veces quieras, y la exporta a código de automatización. Es la puerta de entrada más accesible a la automatización de navegadores, y también una herramienta de diagnóstico por sí misma: convertir un bug reproducible en una secuencia que se ejecuta con un clic cambia por completo la economía de investigarlo.

🎯 Al terminar esta lección sabrás
  • Grabar un flujo y entender qué captura de cada interacción.
  • Interpretar y corregir los selectores que elige automáticamente.
  • Editar los pasos y añadir esperas y aserciones.
  • Reproducir midiendo el rendimiento de cada paso.

Grabar

El panel se abre por su nombre desde el menú de comandos. Al crear una grabación pide un nombre y empieza a registrar; a partir de ahí, cada interacción se convierte en un paso.

Lo que captura de cada interacción son tres cosas: el tipo de acción —clic, escritura, cambio, envío, desplazamiento—, el objetivo expresado con varios selectores alternativos, y los parámetros de la acción, como el texto escrito o las coordenadas.

También registra automáticamente las navegaciones y añade esperas implícitas entre pasos, esperando a que la página se estabilice antes de continuar.

Al terminar, la grabación queda guardada como una lista de pasos editable.

💡
Tip

Graba flujos cortos. Una grabación de cuarenta pasos que cubre tres funcionalidades se rompe constantemente y es imposible de mantener. Varias grabaciones de cinco a diez pasos, cada una cubriendo una cosa, se mantienen solas y se pueden combinar después en el código exportado.

Los selectores y por qué importan

Para cada objetivo, la grabadora genera varios selectores alternativos, en un orden de preferencia que va de lo más estable a lo más frágil.

Selectores por atributo de prueba. Si tus elementos tienen un atributo específico para pruebas, se usa ese, y es con diferencia el más robusto porque no cambia con el rediseño.

Selectores por texto. Buscan el elemento por su contenido visible. Son legibles y se rompen al traducir o al cambiar la redacción.

Selectores de accesibilidad. Basados en el rol y el nombre accesible. Son muy buenos: estables, semánticos, y además su uso obliga a que el elemento tenga un nombre accesible correcto.

Selectores CSS estructurales. Rutas basadas en la posición en el árbol. Son los más frágiles y los que se generan cuando no hay nada mejor.

Al reproducir, se prueban en orden hasta que uno funcione, lo que da cierta tolerancia a los cambios.

La conclusión práctica es importante y va más allá de esta herramienta: si tus grabaciones generan selectores estructurales, tu marcado no es identificable, y eso afecta a la automatización, a las pruebas y a la accesibilidad a la vez. Añadir atributos de prueba a los elementos interactivos principales es media hora de trabajo que hace robusta toda la automatización futura.

El panel permite además configurar qué atributo se prefiere, para que use el convenio de tu proyecto.

Editar la grabación

Cada paso se puede modificar, reordenar, duplicar o eliminar, y se pueden añadir pasos que no se pueden grabar interactuando.

Esperas explícitas por condición. El tipo de paso más útil de todos: esperar a que aparezca un elemento, a que desaparezca, o a que un texto cambie. Sustituir las esperas implícitas por condiciones concretas es lo que convierte una grabación inestable en fiable.

Cambios de tamaño de ventana, para probar la misma secuencia en distintos anchos.

Navegaciones directas, para saltar a un punto sin recorrer el camino.

Aserciones, expresadas como pasos de espera sobre una condición que debe cumplirse: si no se cumple, la reproducción falla y ahí está el fallo de la prueba.

Cada paso tiene además su propio tiempo límite, lo que permite dar más margen a una operación que se sabe lenta sin alargar todas las demás.

Reproducir con medición

Además de reproducir, el panel permite hacerlo midiendo el rendimiento, lo que produce un perfil con la secuencia marcada paso a paso.

Esa combinación es más potente de lo que parece: obtienes un perfil de rendimiento donde cada paso del flujo aparece delimitado, así que puedes ver exactamente qué trabajo corresponde a qué interacción. Es la forma más limpia de responder a “qué está haciendo la aplicación cuando el usuario pulsa aquí”.

Y como la reproducción es determinista en cuanto a la secuencia, se pueden comparar dos ejecuciones de la misma grabación —antes y después de un cambio— con la garantía de que las acciones fueron idénticas. Eso elimina una de las mayores fuentes de ruido al comparar perfiles: que las dos veces no hiciste exactamente lo mismo.

La reproducción admite también condiciones de red y de CPU, con lo que se puede grabar un flujo una vez y reproducirlo bajo distintas configuraciones de dispositivo objetivo.

Prepararse para que esto funcione

Tres cosas en el código de la aplicación multiplican el valor de esta herramienta, y las tres son buenas prácticas por otros motivos.

Atributos de prueba en los elementos interactivos. Estables, semánticos y aparte de las clases de estilo, para que un rediseño no los toque.

<!-- Elementos preparados para la automatizacion y para la accesibilidad -->
<button data-test="anadir-al-carrito" aria-label="Anadir Camiseta azul al carrito">
  Anadir al carrito
</button>

<div data-test="panel-carrito" role="dialog" aria-labelledby="titulo-carrito">
  <h2 id="titulo-carrito">Tu carrito</h2>
  <ul data-test="lista-carrito"></ul>
  <p data-test="total-carrito">0,00 euros</p>
</div>

Señales explícitas de estado. Un atributo que indique que una carga ha terminado, que una operación está en curso o que hay un error, da a la automatización una condición concreta que esperar en lugar de un tiempo arbitrario.

// Señalizar el estado en el DOM para que la automatizacion pueda esperarlo
function marcarEstado(elemento, estado) {
  elemento.dataset.estado = estado;               // 'cargando' | 'listo' | 'error'
  elemento.setAttribute('aria-busy', String(estado === 'cargando'));
}

async function cargarPedidos(contenedor) {
  marcarEstado(contenedor, 'cargando');
  try {
    const r = await fetch('/api/pedidos');
    if (!r.ok) throw new Error('respuesta ' + r.status);
    const datos = await r.json();
    contenedor.innerHTML = datos.map(p => '<li>' + p.id + '</li>').join('');
    contenedor.dataset.cuantos = String(datos.length);
    marcarEstado(contenedor, 'listo');
  } catch (e) {
    contenedor.dataset.error = e.message;
    marcarEstado(contenedor, 'error');
  }
}

Con ese patrón, una aserción de la grabación puede esperar a que el atributo de estado valga lo esperado, que es una condición precisa. Y el atributo de ocupación es información de accesibilidad legítima, no un añadido para las pruebas.

Nombres accesibles correctos. Además de ser un requisito de accesibilidad, hacen que los selectores por rol y nombre funcionen, que son los más estables de todos.

Grabar un bug es la forma más eficiente de investigarlo, y casi nadie lo hace

El uso de esta herramienta del que menos se habla es también el más rentable, y no tiene nada que ver con las pruebas automatizadas. Cuando investigas un bug que requiere una secuencia de siete pasos para reproducirse —entrar, buscar, filtrar, abrir un elemento, cambiar una pestaña, editar un campo, guardar— vas a repetir esa secuencia decenas de veces durante la sesión. Cada repetición cuesta entre treinta segundos y dos minutos, y lo peor no es el tiempo: es que cada repetición es ligeramente distinta, así que cuando el fallo no se reproduce nunca sabes si es porque tu hipótesis era correcta o porque esta vez hiciste algo diferente. Esa incertidumbre contamina todo el razonamiento y es la razón de que las sesiones de depuración de bugs con reproducción larga sean tan agotadoras. Grabar la secuencia una vez, al principio, elimina las dos cosas: la reproducción cuesta un clic y es idéntica cada vez. A partir de ahí puedes cambiar una variable —una condición de red, un valor en el almacenamiento, una versión del código con un punto de parada puesto— y saber con certeza que lo único que ha cambiado es esa variable. Es bisección limpia en lugar de bisección con ruido. Y hay dos usos derivados que valen mucho. Uno: adjuntar la grabación al ticket. Un bug reportado con su secuencia grabada es un bug que cualquiera del equipo puede reproducir en diez segundos, y eso cambia por completo la probabilidad de que se arregle. Dos: convertirla en la prueba de regresión. Cuando arregles el bug, exporta la grabación como script, añade una aserción sobre el comportamiento correcto, y ya tienes la prueba que impide que vuelva, escrita con un esfuerzo marginal sobre trabajo que ibas a hacer de todas formas. Esa secuencia —grabar para investigar, exportar para prevenir— es probablemente la mejor relación entre esfuerzo y valor de todo este track.