No todos los tests son iguales. Cada tipo responde una pregunta distinta. Usar el tipo equivocado es como usar un martillo para atornillar: funciona, pero el resultado es frágil.
ms ms–s s–min ms TDD no es una técnica de testing. Es una técnica de diseño. El test es el primer consumidor de tu API — si es incómodo de testear, es incómodo de usar.
Un test mal escrito es peor que ningún test — da falsa confianza y hace perder tiempo cuando falla por razones equivocadas.
✅ should_return_422_when_email_is_missing() ❌ test_validation_1() ✅ // Arrange
const user = buildUser()
// Act
const result = validate(user)
// Assert
expect(result.error).toBe("email required") ❌ // Todo mezclado
const r = validate(buildUser())
expect(r.error).toBeTruthy() ✅ test("retorna 422 si falta email")
test("retorna 422 si email es inválido") ❌ test("validación de email funciona") ✅ expect(service.getTotal(cart)).toBe(150) ❌ expect(service.calculateTax).toHaveBeenCalledTimes(1) ✅ beforeEach(() => { user = await createTestUser() }) ❌ class UserTest extends BaseTest { ... } ✅ mockEmailService.send = jest.fn() ❌ mockUserRepository.save = jest.fn() // esto es integración, no unit Si los tests no corren en CI, no existen. El pipeline es el guardián que impide que el código roto llegue a producción.
ESLint / Biome TypeScript / tsc Vitest / Jest Vitest / Playwright c8 / istanbul Playwright / Cypress ≥ 80% El mínimo viable. Si no ejecutás una línea en tests, no sabés si funciona. ≥ 70% Cada if/else, cada switch, cada try/catch debe tener ambos caminos testeados. ≥ 85% Si una función no se llama en tests, probablemente es código muerto.