Testear age=30 cuando un campo acepta valores de 18 a 120 no dice nada sobre qué pasa con 17 o 18, que es exactamente donde viven los bugs de off-by-one. La partición de equivalencia agrupa todas las entradas por comportamiento esperado para que elijas un representante por grupo en lugar de repetir casos equivalentes; el análisis de valores límite después apunta a los valores en el borde de cada partición, donde un >= 18 escrito accidentalmente como > 18 pasa desapercibido. Esta guía cubre ambas técnicas con ejemplos prácticos, cómo combinarlas en un proceso de diseño de tests repetible de 10 minutos, y cómo traducir los resultados en tests parametrizados de Playwright.
Qué es la partición de equivalencia
La partición de equivalencia (PE) divide todos los valores de entrada posibles en grupos (llamados particiones o clases de equivalencia) donde se espera que cada valor del grupo se comporte de la misma manera. Si el sistema maneja correctamente un valor de una partición, manejará todos de la misma forma. Entonces solo necesitas testear un representante de cada partición.
Ejemplo: campo de edad para un servicio de streaming
Supongamos que el sistema tiene estas reglas:
- Los usuarios deben tener 18 años o más para registrarse
- Los usuarios menores de 13 están completamente bloqueados
- Los usuarios de 13 a 17 obtienen una cuenta "teen" con restricciones
- Los usuarios de 18 en adelante obtienen una cuenta completa
- La edad debe ser un número entero entre 1 y 120
Se pueden identificar las particiones de inmediato:
| Partición | Rango | Tipo | Resultado esperado |
|-----------|-------|------|-------------------|
| Adulto válido | 18–120 | Válido | Cuenta completa |
| Teen válido | 13–17 | Válido | Cuenta teen |
| Menor de 13 | 1–12 | Inválido | Bloqueado |
| Cero o negativo | ≤ 0 | Inválido | Error |
| Mayor al máximo | > 120 | Inválido | Error |
| No entero | 17.5, "abc", "" | Inválido | Error de validación |
De estas particiones, eliges un representante de cada una. No necesitas testear age=19, age=25, age=50 y age=100. Están todos en la misma partición. Testear age=30 cubre todos ellos.
Los casos de prueba quedan así:
30→ Cuenta completa (partición adulto válido)15→ Cuenta teen (partición teen válido)10→ Bloqueado (partición menor de 13)-1→ Error (partición cero/negativo)200→ Error (partición mayor al máximo)"diecisiete"→ Error de validación (partición no entero)
6 tests en lugar de potencialmente cientos. Y sin perder cobertura.
Qué es el análisis de valores límite
El análisis de valores límite (AVL) se basa en un hecho bien observado: los bugs tienden a agruparse en los bordes de las particiones, no en el medio.
Los desarrolladores escriben código como if (age >= 18). El bug casi nunca es "funciona para 30, se rompe para 31." El bug casi siempre está en el límite: "funciona para 18, se rompe para 17" o "quería usar >= pero escribió >", y el corte queda desfasado por uno.
El AVL dice: en lugar de elegir cualquier representante de cada partición, siempre testea los valores justo en el límite: el último valor válido, el primer valor válido y opcionalmente los valores justo fuera del rango.
Valores del AVL a testear
Para cualquier límite, testeas:
- Último valor antes del rango válido (justo por debajo del mínimo)
- Primer valor válido (mínimo)
- Último valor válido (máximo)
- Primer valor después del rango válido (justo por encima del máximo)
Para el ejemplo de edad con límites en 1, 12, 13, 17, 18, 120:
| Límite | Valores a testear | Por qué |
|--------|------------------|---------|
| Edad mínima válida (1) | 0, 1 | Errores de off-by-one |
| Límite teen/bloqueado (13) | 12, 13 | Asignación correcta de partición |
| Límite teen/adulto (18) | 17, 18 | El bug más común en reglas de negocio |
| Edad máxima válida (120) | 120, 121 | Aplicación del límite superior |
Los casos de prueba del AVL:
0→ Error (por debajo del mínimo)1→ Bloqueado (entrada mínima válida)12→ Bloqueado (último valor en la partición menor de 13)13→ Cuenta teen (primer valor en la partición teen)17→ Cuenta teen (último valor en la partición teen)18→ Cuenta completa (primer valor en la partición adulto)120→ Cuenta completa (último valor en el rango válido)121→ Error (primer valor sobre el máximo)
Es mucho más exhaustivo que el testing aleatorio y mucho más probable que detecte errores reales de off-by-one.
PE y AVL funcionan juntos
En la práctica, los usas juntos:
1. PE primero: identificar todas las particiones (válidas, inválidas, casos límite)
2. AVL segundo: para cualquier partición con un rango numérico u ordenado, testear en los límites en lugar de (o además de) un valor aleatorio en el medio
Así se ve la cobertura combinada para el campo de edad:
| Test | Entrada | Técnica | Resultado esperado |
|------|---------|---------|-------------------|
| 1 | -1 | AVL (bajo el mínimo) | Error |
| 2 | 0 | AVL (en el fondo absoluto) | Error |
| 3 | 1 | AVL (mínimo válido) | Bloqueado |
| 4 | 12 | AVL (último bloqueado) | Bloqueado |
| 5 | 13 | AVL (primer teen) | Cuenta teen |
| 6 | 15 | PE (medio de la partición teen) | Cuenta teen |
| 7 | 17 | AVL (último teen) | Cuenta teen |
| 8 | 18 | AVL (primer adulto) | Cuenta completa |
| 9 | 30 | PE (medio de la partición adulto) | Cuenta completa |
| 10 | 120 | AVL (último válido) | Cuenta completa |
| 11 | 121 | AVL (primero sobre el máximo) | Error |
| 12 | "abc" | PE (partición no entero) | Error de validación |
| 13 | "" | PE (partición vacía) | Error de validación |
13 casos de prueba. Detectarán casi todos los bugs reales de validación de edad, incluyendo los sutiles.
Aplicar esto a funcionalidades reales
Longitud de contraseña (8–64 caracteres)
Particiones
- Vacía → error
- Muy corta (1–7) → error
- Válida (8–64) → aceptada
- Muy larga (65+) → error
Tests del AVL en cada límite
""(vacía) → error7 caracteres→ error (último valor por debajo del mínimo)8 caracteres→ aceptada (primer valor válido)64 caracteres→ aceptada (último valor válido)65 caracteres→ error (primer valor sobre el máximo)
20 caracteres → aceptada
Son 6 tests que cubren todo el rango válido/inválido.
Campo de email
Este es un escenario solo de partición (sin límites numéricos limpios):
Particiones
- Vacío → error
- Formato válido (nombre@dominio.com) → aceptado
- Falta el @ → error
- Falta el dominio → error
- Múltiples @ → error
- Caracteres internacionales → depende de la especificación del sistema
Testea un valor de cada partición. No testeas 50 formatos de email válidos: todos van en la partición "formato válido".
Dropdown con valores fijos
Si un campo solo acepta valores específicos (Pequeño/Mediano/Grande), no hay límites que analizar con AVL. La PE es suficiente: un valor válido (Mediano) se acepta, un valor inválido no en la lista (XL) da error, y el campo vacío también da error.
Errores comunes que hay que evitar
Testear demasiados valores de la misma partición
Si testeas ages 20, 25, 30, 35 y 45, escribiste 5 tests que viven en la misma partición. Todos pasarán o todos fallarán juntos. No ganaste nada con esos 4 tests extra.
La corrección: elige un representante por partición y testea en los límites.
Olvidar las particiones inválidas
Los principiantes a menudo solo piensan en la entrada válida. Los bugs reales viven en lo que pasa con la entrada inválida: números negativos, cadenas vacías, valores ligeramente demasiado grandes.
La corrección: siempre lista las particiones inválidas explícitamente. A menudo ahí se esconden los bugs interesantes.
Perder particiones no obvias
Para un campo de "código de descuento", las particiones comunes son código válido, código inválido y vacío. Las fáciles de perder: código vencido, código ya usado, código para un producto diferente, código con mayúsculas/minúsculas incorrectas (¿es sensible al caso?).
La corrección: piensa en el comportamiento del sistema, no solo en el formato. Comportamientos diferentes = particiones diferentes.
Aplicar AVL a datos no ordenados
El AVL solo tiene sentido para datos que tienen un orden natural: números, fechas, longitudes. No puedes aplicar AVL a una lista de códigos de país o un conjunto de valores de enum. Para esos, usa PE.
Un proceso práctico
Cuando encuentras cualquier campo de entrada o regla de negocio, sigue estos pasos:
Paso 1: ¿Qué valores acepta este campo? ¿Cuáles son las reglas? Paso 2: Listar todas las particiones, las válidas y las inválidas. Escribe el comportamiento esperado para cada una. Paso 3: Para cualquier partición con un rango numérico u ordenado, identificar los límites. Listar los valores último-inválido/primer-válido y último-válido/primer-inválido. Paso 4: Elegir un representante de cada partición que no sea de límite (para el medio de los rangos válidos). Agregar los valores límite. Paso 5: Escribir los casos de prueba, uno por cada valor identificado.Esto lleva de 5 a 10 minutos por funcionalidad y te da un conjunto de tests eficiente y justificable que podés explicar a cualquier persona.
Por qué esto importa para la automatización QA
Al escribir tests de Playwright, estas técnicas ayudan a decidir qué parametrizar. En lugar de escribir 20 tests casi idénticos que solo cambian el valor de entrada, escribes un test parametrizado con los 6 a 8 valores que identificaron la PE y el AVL:
const CASOS_EDAD = [
{ input: '-1', esperado: 'error', etiqueta: 'bajo el mínimo' },
{ input: '1', esperado: 'bloqueado', etiqueta: 'mínimo válido' },
{ input: '12', esperado: 'bloqueado', etiqueta: 'último bloqueado' },
{ input: '13', esperado: 'cuenta teen', etiqueta: 'primer teen' },
{ input: '17', esperado: 'cuenta teen', etiqueta: 'último teen' },
{ input: '18', esperado: 'cuenta completa', etiqueta: 'primer adulto' },
{ input: '120', esperado: 'cuenta completa', etiqueta: 'último válido' },
{ input: '121', esperado: 'error', etiqueta: 'sobre el máximo' },
];
for (const { input, esperado, etiqueta } of CASOS_EDAD) {
test(`edad ${etiqueta}: ${esperado}`, async ({ page }) => {
await page.fill('[data-testid="age-input"]', input);
await page.click('[data-testid="submit"]');
await expect(page.locator('[data-testid="result"]')).toContainText(esperado);
});
}Limpio, legible, y cada test tiene una razón clara de existir.
Conclusiones clave
- La partición de equivalencia agrupa las entradas por comportamiento esperado: testea un valor por grupo
- El análisis de valores límite apunta a los bordes entre grupos, donde viven los bugs de off-by-one
- Usa PE para identificar las particiones, AVL para elegir los valores exactos a testear
- Siempre incluye particiones inválidas: los tests de "qué pasa con entradas incorrectas" detectan bugs reales
- El objetivo es mínimos tests, máxima cobertura, no testear todo, sino testear las cosas correctas