Publicado: Hace 29 días
Hagamos un ejercicio, cerremos los ojos y di en voz alta: “Pruebas en el frontend”.
¿Qué fue lo primero que se te vino a la mente? Seguramente pensaste en el equipo de QA. Esos héroes silenciosos que siempre encuentran el bug que juraste haber probado una y una otra vez.
A grandes rasgos, el equipo de QA se encarga de validar que nuestras aplicaciones funcionen correctamente antes de que lleguen a manos del usuario final. Y para lograrlo, se apoyan de una poderosa herramienta: pruebas automatizadas.
Son bloques de código encargados de validar otro bloques de código. Así como lo lees, escribimos código para revisar nuestro propio código. Bastante raro si es tu primera vez.
Estas pruebas se dividen principalmente en tres tipos:
Validan unidades pequeñas de código de forma aislada. Una función, un componente, una lógica de negocio en concreto.
Se aseguran que dos o más piezas de código se comuniquen correctamente entre si.
Simulan el comportamiento de un usuario real: entrar a tu app, hacen clics, llenan formularios, navegan entre pantallas.
El equipo de QA suele apoyarse de las pruebas de extremo a extremo para validar toda la aplicación. Son pruebas más costosas de implementar y mantener, pero también más confiables, ya que evalúan la aplicación desde la perspectiva del usuario final.
Mientras tanto, nuestra responsabilidad como desarrolladores frontend, debería ser asegurar nuestros desarrollos mediante pruebas unitarias y de integración.
Estas pruebas son más rápidas, especificas y nos ayudan a detectar errores antes de que el código llegue a QA (o peor aún, a producción).
El problema es que, en muchos equipos frontend, aún se valida todo a mano.
Muchos desarrolladores aún revisan su código manualmente: abrir el navegador, llenan formularios, siguen flujos manualmente… una y otra vez.
Aunque parezca más rápido al principio, validar manualmente de esta forma el frontend conlleva varias cosas:
Y la lista puede seguir creciendo.
Comenzar a escribir pruebas unitarias y de integración en nuestros proyectos frontend no solo es una buena práctica: es una inversión a largo plazo.
Nos permite detectar errores antes de que se conviertan en perdidas monetarias, documentar el comportamiento esperado de cada componente, evitar depender de configuraciones externas y lo más importante: tener la confianza de refactorizar sin miedo a romper algo.
Sí, al principio puede parecer un esfuerzo extra. Pero tu "yo del futuro”, o cualquier otra persona que toque ese código, te lo va a agradecer.
Dicho esto, veamos un ejemplo.
Supongamos que tenemos un listado de categorías y debemos validar que se estén listado correctamente y además, si no existen categorías mostrar un mensaje “No hay categorías disponibles”. Cada mencionar que estas categorías vienen directamente desde el backend. Sin embargo, en lugar de ambientar localmente toda nuestra aplicación, usemos pruebas de integración.
1. Componente para listar categorías
// CategoryList.jsx import React, { useEffect, useState } from 'react'; const CategoryList = ({ categoriesAPI }) => { const [categories, setCategories] = useState([]); useEffect(() => { categoriesAPI().then((data) => { setCategories(data); }); }, [categoriesAPI]); if (!categories.length) { return <p>No hay categorías disponibles.</p>; } return ( <ul> {categories.map((category) => ( <li key={category.id} data-testid="category-item"> {category.name} </li> ))} </ul> ); }; export default CategoryList;
2. Pruebas del componente listar categorías
// CategoryList.test.jsx import { render, screen, waitFor } from '@testing-library/react'; import CategoryList from './CategoryList'; describe('CategoryList', () => { it('muestra mensaje cuando no hay categorías', async () => { const mockCategoriesAPI = jest.fn().mockResolvedValue([]); // Simulamos la data devuelta por el backend render(<CategoryList categoriesAPI={mockCategoriesAPI} />); await waitFor(() => { expect(screen.getByText('No hay categorías disponibles.')).toBeInTheDocument(); }); }); it('muestra la lista de categorías cuando la API devuelve datos', async () => { const mockCategoriesAPI = jest.fn().mockResolvedValue([ { id: 1, name: 'Tecnología' }, { id: 2, name: 'Hogar' }, { id: 3, name: 'Libros' }, ]); // Simulamos la data devuelta por el backend render(<CategoryList categoriesAPI={mockCategoriesAPI} />); const items = await screen.findAllByTestId('category-item'); expect(items).toHaveLength(3); expect(items[0]).toHaveTextContent('Tecnología'); expect(items[1]).toHaveTextContent('Hogar'); expect(items[2]).toHaveTextContent('Libros'); }); });
Realizar pruebas unitarias y de integración en el frontend no solo mejora la calidad de nuestro código: nos permite enfocarnos en lo que realmente importa, la funcionalidad principal, sin depender de todo el ecosistema que lo rodea.
No necesitamos levantar el backend, configurar base de datos ni simular servicios externos para validar que nuestro componente funciona correctamente.
En el mundo del frontend moderno, hacer testing ya no es un lujo… es una herramienta fundamental para construir software de calidad.
📘 ¿Quieres aprender más sobre cómo hacer testing en React?
En mi libro Testing en React. Guía práctica con Jest y React Testing Library, encontrarás todo lo necesario para dominar las pruebas en tus proyectos: desde lo más básico hasta escenarios reales de aplicaciones como Stripe, Duolingo y Amazon.