¿Qué Es Equivalence Partitioning?
Equivalence Partitioning (EP) es una de las técnicas de test design de caja negra más fundamentales. La idea central es simple pero poderosa: en lugar de probar cada input posible, divides el dominio de input en clases de equivalencia — grupos de valores que el sistema debería tratar de forma idéntica.
Si el sistema maneja correctamente un valor de una clase, debería manejar correctamente todos los valores de esa clase. Esta suposición te permite reducir miles de test cases potenciales a un número manejable.
Por Qué Es Importante
Considera un campo que acepta enteros del 1 al 10,000. Probar cada valor requeriría 10,000 test cases — más los valores inválidos. Con equivalence partitioning, necesitas tan solo 3 test cases:
| Clase | Rango | Representante | Esperado |
|---|---|---|---|
| Inválida (baja) | < 1 | -5 | Error |
| Válida | 1–10,000 | 4,500 | Aceptar |
| Inválida (alta) | > 10,000 | 20,000 | Error |
Pasaste de 10,000+ tests a 3, cubriendo toda la lógica central.
El Proceso
Paso 1: Identificar el dominio de input. Revisa la especificación para entender qué acepta el campo o parámetro.
Paso 2: Dividir en clases de equivalencia. Agrupa valores que deberían procesarse de forma idéntica. Cada clase debe ser mutuamente excluyente — un valor pertenece a exactamente una clase.
Paso 3: Seleccionar representantes. Elige un valor de cada clase. Evita los valores límite — esos se cubren con una técnica separada (Boundary Value Analysis).
Paso 4: Escribir test cases. Crea un test case por valor representativo.
Tipos de Clases de Equivalencia
Clases válidas contienen valores que el sistema debería aceptar y procesar normalmente.
Clases inválidas contienen valores que el sistema debería rechazar o manejar como errores.
Un error común es enfocarse solo en las clases válidas. Las clases inválidas frecuentemente revelan más defectos porque el manejo de errores generalmente está sub-testeado.
Aplicando EP a Diferentes Tipos de Datos
Equivalence partitioning funciona con cualquier tipo de input:
Rangos numéricos:
- Campo de edad (18-65): las clases son
<18,18-65,>65
Inputs de texto:
- Username (3-20 caracteres, alfanumérico): las clases incluyen longitud válida + caracteres válidos, muy corto, muy largo, caracteres especiales, string vacío
Enumeraciones:
- Método de pago (tarjeta de crédito, débito, PayPal): cada opción es su propia clase válida; un método no soportado es una clase inválida
Boolean:
- Checkbox (marcado/desmarcado): dos clases válidas
Ejemplo Real: Descuento en E-Commerce
Una tienda aplica descuentos según el total del carrito:
| Total del Carrito | Descuento |
|---|---|
| $0 – $49.99 | 0% |
| $50 – $99.99 | 5% |
| $100 – $199.99 | 10% |
| $200+ | 15% |
Clases de equivalencia:
| # | Clase | Representante | Descuento Esperado |
|---|---|---|---|
| 1 | Valores negativos (inválida) | -$10 | Error |
| 2 | $0 – $49.99 | $25 | 0% |
| 3 | $50 – $99.99 | $75 | 5% |
| 4 | $100 – $199.99 | $150 | 10% |
| 5 | $200+ | $300 | 15% |
Cinco test cases cubren toda la lógica de descuentos.
Equivalence Partitioning Avanzado
Particionamiento Multi-Parámetro
Las aplicaciones reales rara vez tienen un solo input. Cuando tienes múltiples parámetros, cada uno tiene su propio conjunto de clases de equivalencia. El desafío es combinarlos efectivamente.
Ejemplo: Formulario de registro de usuario
| Parámetro | Clases Válidas | Clases Inválidas |
|---|---|---|
| Edad | 18-120 | <18, >120, no numérico |
| formato válido | sin @, sin dominio, vacío | |
| Password | 8-64 chars con mayúscula, minúscula, dígito | muy corto, muy largo, faltan caracteres requeridos |
Para testing de clases válidas, crea un solo test case usando un representante válido de cada parámetro simultáneamente:
Test Case 1: Edad=30, Email=user@test.com, Password=Secure1pass
Esperado: Registro exitoso
Para testing de clases inválidas, varía un parámetro a la vez manteniendo los demás válidos:
Test Case 2: Edad=15, Email=user@test.com, Password=Secure1pass
Esperado: Error de validación de edad
Test Case 3: Edad=30, Email=email-invalido, Password=Secure1pass
Esperado: Error de validación de email
Este enfoque se llama Single Fault Assumption — probar un parámetro inválido a la vez para aislar cuál validación se activa.
Particionamiento Basado en Outputs
A veces es más efectivo particionar basándose en los outputs en lugar de los inputs. Si una función retorna diferentes tipos de resultado, trabaja hacia atrás:
def categorizar_imc(imc):
if imc < 18.5:
return "Bajo peso"
elif imc < 25:
return "Normal"
elif imc < 30:
return "Sobrepeso"
else:
return "Obesidad"
Particiones de output: Bajo peso, Normal, Sobrepeso, Obesidad. Elige un input que active cada output.
Errores Comunes
- Olvidar la clase “vacía”. Siempre considera string vacío, null o cero como una clase separada.
- Ignorar tipos de datos. Un campo numérico podría recibir letras — esa es una clase inválida separada.
- Clases superpuestas. Cada valor debe pertenecer a exactamente una clase. Si las clases se superponen, tu particionamiento está mal.
- Pocas clases inválidas. Generalmente hay más clases inválidas que válidas.
Ejercicio: Diseña Clases de Equivalencia
Escenario: Un sistema de reserva de vuelos acepta los siguientes inputs:
- Pasajeros: 1–9 (entero)
- Clase: Economy, Business, First
- Tipo de viaje: Solo ida, Ida y vuelta
Tarea: Identifica todas las clases de equivalencia para cada parámetro y escribe el conjunto mínimo de test cases necesarios.
Pista
Para Pasajeros: piensa qué pasa con 0, números negativos, 10+, números decimales e input no numérico.
Para Clase y Tipo de viaje: cada opción válida es su propia clase. ¿Qué pasa con una opción que no existe?
Solución
Pasajeros:
| # | Clase | Representante | ¿Válida? |
|---|---|---|---|
| 1 | 1–9 | 4 | Válida |
| 2 | < 1 | 0 | Inválida |
| 3 | > 9 | 15 | Inválida |
| 4 | No entero | 2.5 | Inválida |
| 5 | No numérico | “abc” | Inválida |
Clase:
| # | Clase | Representante | ¿Válida? |
|---|---|---|---|
| 6 | Economy | Economy | Válida |
| 7 | Business | Business | Válida |
| 8 | First | First | Válida |
| 9 | No soportada | “Premium” | Inválida |
Tipo de viaje:
| # | Clase | Representante | ¿Válida? |
|---|---|---|---|
| 10 | Solo ida | Solo ida | Válida |
| 11 | Ida y vuelta | Ida y vuelta | Válida |
| 12 | No soportada | “Multi-ciudad” | Inválida |
Test cases mínimos:
Válidos (todos los representantes válidos combinados):
TC1: Pasajeros=4, Clase=Economy, Viaje=Solo ida → Éxito
TC2: Pasajeros=4, Clase=Business, Viaje=Ida y vuelta → Éxito
TC3: Pasajeros=4, Clase=First, Viaje=Solo ida → Éxito
Inválidos (uno inválido a la vez):
TC4: Pasajeros=0, Clase=Economy, Viaje=Solo ida → Error
TC5: Pasajeros=15, Clase=Economy, Viaje=Solo ida → Error
TC6: Pasajeros=2.5, Clase=Economy, Viaje=Solo ida → Error
TC7: Pasajeros="abc", Clase=Economy, Viaje=Solo ida → Error
TC8: Pasajeros=4, Clase="Premium", Viaje=Solo ida → Error
TC9: Pasajeros=4, Clase=Economy, Viaje="Multi-ciudad" → Error
Total: 9 test cases cubriendo 12 clases de equivalencia.
Tips de Profesional
- Combina EP con Boundary Value Analysis. EP reduce el espacio de input; BVA se enfoca en los bordes de cada clase. Juntas forman la base del testing basado en especificaciones.
- Documenta tus particiones. Antes de escribir test cases, lista todas las clases de equivalencia en una tabla. Esto facilita las revisiones y asegura completitud.
- Revisa las particiones cuando cambian las especificaciones. Un cambio en el rango válido o un nuevo tipo de input significa nuevas clases de equivalencia.
- Usa EP para parámetros de API también. Cada parámetro de endpoint de API tiene clases válidas e inválidas — aplica la misma técnica a request bodies, query parameters y headers.