Testing en frontend: qué probar y qué no

En el día a día de un desarrollador frontend nos encontramos con una gran cantidad de decisiones: ¿qué probar?, ¿con qué herramienta?, ¿hasta dónde llegar con los tests? En este artículo intento aclarar esas dudas y ofrecer una guía práctica que te ayude a centrarte en lo que realmente aporta valor a tu proyecto.
Tipos de pruebas y su objetivo
Antes de decidir qué incluir en la suite de tests, es útil distinguir entre los tres niveles más habituales:
- Tests unitarios: verifican el comportamiento de una función o componente aislado.
- Tests de integración: comprueban la interacción entre varios módulos o componentes.
- Tests end‑to‑end (E2E): simulan el flujo completo del usuario en la aplicación.
Cada nivel tiene un coste de mantenimiento diferente y cubre riesgos distintos. Lo ideal es combinar los tres, pero priorizando los que aportan mayor confianza al menor coste.
Qué probar
Enfócate en la lógica de negocio y en la interacción del usuario, no en la implementación interna. Aquí tienes una lista de los aspectos que sí deben estar cubiertos:
- Lógica de componentes: estados, props y callbacks. Por ejemplo, que un botón cambie su estado al hacer click.
- Funciones puras: cualquier helper que reciba datos y devuelva un resultado sin efectos secundarios.
- Flujos críticos: registro, login, carrito de compra, etc. Un test E2E que recorra todo el proceso garantiza que los usuarios no se encuentren con sorpresas.
- Validaciones de formularios: comprueba que los mensajes de error aparecen cuando los datos son incorrectos y que el envío solo ocurre cuando todo es válido.
- Comportamiento en casos de error: simula respuestas fallidas del servidor y verifica que la UI muestra la información adecuada.
Qué no probar
Algunos aspectos pueden generar ruido y aumentar el coste de mantenimiento sin aportar valor real:
- Detalles de estilo: colores, márgenes o clases CSS. Estos cambios suelen ser gestionados por pruebas visuales o simplemente revisados en el navegador.
- Implementación de librerías externas: no tiene sentido testear que
axiosdevuelve una promesa, confía en su propia suite de tests. - Componentes demasiado triviales: un componente que solo muestra texto estático rara vez necesita pruebas unitarias, a menos que forme parte de una lógica más compleja.
- Snapshots demasiado amplios: los snapshots que capturan toda la salida de un componente pueden romperse con cambios menores de UI, generando falsos positivos.
Consejos prácticos para mantener una suite saludable
- Escribe tests que describan comportamiento, no estructura. Pregúntate "¿Qué debería pasar cuando el usuario hace X?" en lugar de "¿Cuál es el árbol DOM exacto?".
- Utiliza factories o builders para crear datos de prueba consistentes y fáciles de leer.
- Mockea las dependencias externas (APIs, storage) con herramientas como
mswo jest mocks. Así mantienes los tests rápidos y deterministas. - Ejecuta los tests en modo watch durante el desarrollo; así detectas errores inmediatamente.
- Revisa la cobertura pero no persigas el 100%. Prefiere cubrir lógica importante antes que líneas triviales.
Ejemplo práctico
Supongamos que tenemos un componente Counter que muestra un número y tiene dos botones para incrementarlo y resetearlo. Queremos probar que la lógica de incremento funciona y que el botón de reset vuelve a 0.
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';
test('incrementa el contador al pulsar el botón +1', () => {
render(<Counter />);
const button = screen.getByRole('button', { name: /+1/i });
const value = screen.getByTestId('value');
expect(value).toHaveTextContent('0');
fireEvent.click(button);
expect(value).toHaveTextContent('1');
});
test('restablece el contador a 0', () => {
render(<Counter />);
const inc = screen.getByRole('button', { name: /+1/i });
const reset = screen.getByRole('button', { name: /reset/i });
const value = screen.getByTestId('value');
fireEvent.click(inc);
fireEvent.click(inc);
expect(value).toHaveTextContent('2');
fireEvent.click(reset);
expect(value).toHaveTextContent('0');
});
Observa cómo el test se centra en el comportamiento observable (value) y no en la implementación interna del estado. Con este enfoque, si cambiamos la manera de almacenar el contador (por ejemplo, usando useReducer) los tests seguirán pasando.
Resumen
El objetivo del testing en frontend es dar confianza al cambiar código, no crear una carga de mantenimiento imposible. Prioriza la lógica de negocio y los flujos críticos, evita probar estilos y dependencias externas, y mantén los tests legibles y enfocados en el comportamiento del usuario. Con esa mentalidad, tu suite será una herramienta poderosa y no una pesadilla.