Inicio / Artículos / Pruebas de componentes React con Vitest y Testing Library

Pruebas de componentes React con Vitest y Testing Library

Conecta Wire Vitest con Vite, coloca pruebas de comportamiento, ejecuta pruebas en watch frente a CI, y instruye a un agente de IA para que siga un ciclo de verificación en rojo-verde.

773 palabras

Vitest es un ejecutor de pruebas rápido y nativo de Vite que resulta familiar si ya conoces Jest; además, funciona perfectamente junto con React Testing Library para pruebas de comportamiento de componentes. Esta guía aborda la configuración, un ciclo práctico de tipo rojo-verde, la estructura de los archivos y cómo instruir a un agente de programación por IA para que ayude en lugar de generar resultados inútiles.

1. Configuración del proyecto

Instala la típica pila de pruebas de React como dependencias de desarrollo:

npm install -D vitest jsdom @testing-library/react @testing-library/jest-dom @testing-library/user-event

En un proyecto React con Vite, informa a Vitest sobre la aplicación dentro de vite.config.ts para que los alias y plugins coincidan con las compilaciones en producción:

For a Vite React project, add Vitest to vite.config.ts:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
  plugins: [react()],
  test: {
    environment: 'jsdom',
    setupFiles: ['./src/test/setup.ts'],
    globals: true,
  },
})

environment: 'jsdom' proporciona APIs del DOM sin necesidad de un navegador real. Un pequeño archivo de configuración registra los comparadores de jest-dom una sola vez para cada conjunto de pruebas:

import '@testing-library/jest-dom/vitest'

Integre ese archivo a través de la opción setupFiles de Vitest para que afirmaciones como toBeInTheDocument y toHaveAccessibleName funcionen en cualquier lugar.

2. Flujo de trabajo recomendado

Utilice un ciclo estricto: Funcionalidad → Prueba → Implementación → Verificación → Refactorización.

  1. Entienda la funcionalidad — enumere el comportamiento visible para el usuario y los estados importantes (cargando, éxito, error, vacío, deshabilitado). Anote los límites de la API o del navegador que requieran simulaciones para que las pruebas sigan siendo deterministas.
  2. Escriba la prueba primero — prefiera las consultas de React Testing Library; verifique los resultados que el usuario percibe, no el estado privado; realice clics y escritura con userEvent para mayor realismo.
  • Implemente lo mínimo necesario — mantenga el código de producción enfocado en satisfacer la prueba que falló; evite mecanismos exclusivos para pruebas o detalles internos expuestos, a menos que no exista una solución más limpia.
  • Ejecute pruebas dirigidas mientras itera, de modo que la retroalimentación llegue en segundos y no en minutos:
  • npx vitest run src/components/Button.test.tsx
    
    During development:
    

    Modo de observación para el bucle de retroalimentación local:

    npx vitest
    
    Run the full suite
    

    Conjunto completo mediante la script de npm que expone su package.json:

    npm test
    

    o una ejecución única al estilo CI sin monitores:

    npx vitest run
    
    Check coverage when appropriate
    

    Cobertura para destacar las ramas no probadas:

    npx vitest run --coverage
    

    Trate la cobertura como una guía, no como un porcentaje vacío; prefiera afirmaciones significativas en lugar de buscar el 100 %.

    3. Estructura de las pruebas

    Coloque las pruebas junto a los componentes que protegen:

    src/
    ├── components/
    │   ├── LoginForm.tsx
    │   └── LoginForm.test.tsx
    ├── hooks/
    │   ├── useUser.ts
    │   └── useUser.test.ts
    ├── pages/
    │   ├── Dashboard.tsx
    │   └── Dashboard.test.tsx
    └── test/
        ├── setup.ts
        └── mocks/
    
    For a component, structure tests around behavior:
    

    Diseñe los casos en torno a los resultados del usuario y no a los nombres de los métodos:

    describe('LoginForm', () => {
      it('allows a user to submit valid credentials', async () => {
        // arrange
        // act
        // assert
      })
    
      it('shows validation errors for invalid input', async () => {
        // ...
      })  it('disables submission while logging in', async () => {
        // ...
      })
    })
    

    Cubra la ruta normal, los fallos de validación y los estados deshabilitados o en carga en bloques it separados. Cuando algo falla, el título del caso fallido debe indicar un comportamiento específico. Utilice los auxiliares de organización con moderación; una configuración duplicada pero clara es mejor que fixtures ingeniosos que oculten la intención.

    4. Trabajar con un agente de codificación de IA

    4. Vitest-agent prompt
    

    Indique al agente que actúe como un ingeniero senior de pruebas en React: escriba o actualice primero la prueba que falla, implemente el cambio más mínimo y luego verifique con Vitest y haga la comprobación de tipos:

    npx vitest run <target-test>
    npx vitest run
    npm run typecheck
    npm run lint
    

    Pídale que prefiera las consultas de Testing Library (getByRole, findByText) en lugar de selectores CSS frágiles, que simule los límites de red en vez de acceder al estado del componente, y que deje una breve nota cuando una prueba documente una restricción intencional del producto.

    Hábitos de cierre

    Mantenga la configuración de Vitest compartida con Vite para que los alias de rutas y los plugins coincidan con el entorno de producción. Prefiera usar run en CI y observar los resultados localmente. Amplíe las suites a medida que se añaden nuevas funcionalidades, y no mediante una reescritura masiva. Con este ciclo —prueba primero, implementa, verifica— las aplicaciones React siguen siendo refactorizables sin ralentizar el ciclo de retroalimentación impulsado por Vite, que fue lo que hizo atractivo a Vitest en primer lugar.

    Lecturas relacionadas