Pruebas: tu red de seguridad
Una prueba (test) es código que comprueba que otro código hace lo que esperas. Una vez escrita, se ejecuta en segundos y te avisa de inmediato si algo se ha roto.
Un conjunto de pruebas saludable tiene forma de pirámide: muchas pruebas unitarias pequeñas y rápidas en la base, menos pruebas de integración en el medio, y solo un puñado de pruebas de extremo a extremo lentas en la cima. La mayor parte de tu seguridad viene barata desde abajo:
╱╲
╱ ╲ E2E few · slow · whole app
╱────╲ (end-to-end)
╱ ╲
╱ INTEG ╲ INTEGRATION some · medium
╱──────────╲ (parts together)
╱ ╲
╱ UNIT ╲ UNIT many · fast · one function
╱────────────────╲
cheap base = most of your tests
No necesitas una cobertura del 100%. Empieza probando las cosas que más dolerían si se rompieran: inicio de , pagos, datos que no se pueden regenerar, lógica de negocio central. La IA es excelente escribiendo pruebas — a menudo mejor que escribiendo funcionalidades, porque el comportamiento esperado es concreto.
Aquí tienes un que funciona bien:
Write tests for the calculateDiscount function in src/pricing.js.
Cover: a normal case, the zero/empty case, the maximum-discount
boundary, and one invalid input. Use the existing test setup in
this repo (check how other *.test.js files are structured).
Run the tests and show me they pass before you finish.
Esa última línea importa. Pide siempre a la IA que ejecute las pruebas, no solo que las escriba. Una prueba que nunca se ejecutó es una suposición. También vale la pena ser específico sobre qué casos cubrir, porque dejada a su aire la IA tiende a escribir tres variaciones del camino feliz y llamarlo exhaustivo. Los casos que realmente detectan errores son los aburridos: entrada vacía, el valor límite, lo que debería lanzar una excepción.
Un ejemplo sencillo de lo que debería producir:
import { calculateDiscount } from "./pricing.js";
import { describe, it, expect } from "vitest";
describe("calculateDiscount", () => {
it("applies a normal percentage discount", () => {
expect(calculateDiscount(100, 0.2)).toBe(80);
});
it("returns the full price when discount is zero", () => {
expect(calculateDiscount(100, 0)).toBe(100);
});
it("never discounts below zero", () => {
expect(calculateDiscount(100, 1.5)).toBe(0);
});
it("rejects a negative price", () => {
expect(() => calculateDiscount(-10, 0.2)).toThrow();
});
});
Cuando más adelante cambies una funcionalidad, ejecuta primero las pruebas. Si se ponen en rojo, encontraste la rotura antes que tus usuarios. Cuando la IA arregle un error, pídele que añada una prueba que falle con el comportamiento antiguo — así el error no puede volver silenciosamente. Este hábito tiene un nombre: la prueba de regresión. Cada error que encuentras es una lección que el código ya pagó; una prueba de regresión es cómo conservas la lección.
Una advertencia: una prueba también puede estar equivocada. Si la IA escribe una prueba que afirma que el comportamiento defectuoso es correcto, pasará para siempre mientras tu aplicación sigue rota. Así que lee las aserciones, no solo las marcas verdes. Una prueba que pasa solo significa "el código hace lo que dice la prueba" — todavía tienes que confirmar que la prueba dice lo correcto.