Partición de equivalencia: Técnica de diseño de pruebas explicada con ejemplos resueltos
No puedes probar todas las entradas posibles, entonces, ¿qué valores deberías elegir? La partición de equivalencia le da una respuesta clara. Aprenda el método paso a paso, trabaje con ejemplos reales y vea dónde necesita ayuda.
- La partición de equivalencia divide las entradas en grupos que deberían comportarse de la misma manera.
- Se prueba un valor representativo de cada grupo en lugar de cada valor.
- Incluya siempre particiones inválidas, ya que el manejo de errores es donde se esconden muchos errores.
- Funciona mejor junto con el análisis de valores límite, porque los errores a menudo se ubican en los bordes de un grupo.
Un campo de edad que acepta entre 18 y 60 años tiene una enorme cantidad de entradas posibles, una vez que se cuentan los negativos, los números enormes, el texto y los espacios en blanco. Nadie puede probarlos todos. La partición de equivalencia resuelve esto agrupando las entradas que el software debe tratar de la misma manera y luego probando un valor de cada grupo.
Es una de las primeras técnicas de diseño de pruebas que todo evaluador debería aprender. En esta guía lo analizamos paso a paso y probamos un ejemplo en Python. Ejecutamos ese código en Python 3.13 y se incluye su resultado. Las reglas de contraseñas y cupones que aparecen a continuación son ejemplos ilustrativos, no tomados de un sistema real.
¿Qué es la partición de equivalencia?
La partición de equivalencia, también llamada partición de clases de equivalencia (ECP), es una técnica de diseño de pruebas de caja negra. Divide las posibles entradas de una característica en particiones o clases. Se espera que cada valor dentro de una partición produzca el mismo tipo de comportamiento.
Como no necesita ver el código, puede aplicarlo directamente desde un requisito. Para obtener más información sobre este estilo de prueba, lea prueba de caja negra versus prueba de caja blanca.
Por que funciona
La técnica se basa en una suposición: si un valor en una partición encuentra un error, los demás en esa partición probablemente también lo encontrarán. Y si un valor se aprueba, los demás probablemente también se aprobarán. Es probable que realizar pruebas a 25, 26 y 27 años en un campo de edad adulta no le diga nada que la prueba a 25 por sí sola no le diga.
| Enfoque | Pruebas para un campo de edad. | Resultado |
|---|---|---|
| exhaustivo | Cada valor posible | Imposible en la práctica |
| adivinanzas aleatorias | Lo que sea que se te ocurra | Duplicados y lagunas |
| Partición de equivalencia | Uno por partición | Pequeño, con cobertura deliberada |
Sin embargo, es una suposición y no una garantía. El software puede tener casos especiales ocultos dentro de una partición, una limitación a la que volveremos más adelante.
Cómo hacerlo en cinco pasos
- Lea el requisito e identifique la entrada y sus reglas.
- Encuentre las particiones válidas, cuáles son los grupos de valores que deben aceptarse y observe si diferentes rangos se comportan de manera diferente.
- Encuentre las particiones no válidas, incluidos valores demasiado bajos, demasiado altos, del tipo incorrecto y en blanco.
- Elija un valor representativo de cada partición, generalmente en algún punto intermedio.
- Escriba el resultado esperado para cada uno, como en cualquier buen caso de prueba.
Ejemplo resuelto: un campo de edad
Requisito: Pueden registrarse usuarios de entre 18 y 60 años.
| Partición | Tipo | Valor de prueba | Resultado esperado |
|---|---|---|---|
| Menos de 18 | Inválido | 10 | Rechazado |
| 18 a 60 | Válido | 35 | Aceptado |
| Más de 60 | Inválido | 75 | Rechazado |
| no es un numero | Inválido | “abc” | error |
| En blanco | Inválido | (empty) | Mensaje “obligatorio” |
Cinco pruebas le brindan cobertura de cada comportamiento del requisito. Muchos tutoriales se detienen en las tres primeras filas, pero las dos últimas son las que los usuarios reales activan por accidente. También puede agregar filas para números negativos o decimales, si es razonable manejarlos de manera diferente.
Probándolo en código
Aquí está esa regla como una función, con una prueba unitaria por partición, usando la función incorporada de Python unittest:
import unittest
def can_register(age):
if not isinstance(age, int) or isinstance(age, bool):
raise TypeError("age must be a whole number")
return 18 <= age <= 60
class EquivalenceTests(unittest.TestCase):
def test_valid_partition(self):
self.assertTrue(can_register(35))
def test_too_young_partition(self):
self.assertFalse(can_register(10))
def test_too_old_partition(self):
self.assertFalse(can_register(75))
def test_wrong_type_partition(self):
with self.assertRaises(TypeError):
can_register("abc")
Nuestra carrera pasó:
test_too_old_partition ... ok
test_too_young_partition ... ok
test_valid_partition ... ok
test_wrong_type_partition ... ok
En un proyecto real, la función de parametrización de pytest es una forma sencilla de ejecutar una tabla de valores de partición a través de una única prueba.
Ejemplo resuelto: una contraseña
Requisito: Una contraseña debe tener entre 8 y 20 caracteres y contener al menos un dígito.
Este tiene dos reglas, longitud y contenido, por lo que consideramos particiones para ambas:
| Partición | Tipo | Valor de prueba | Resultado esperado |
|---|---|---|---|
| Longitud válida, tiene un dígito. | Válido | amanecer42 |
Aceptado |
| demasiado corto | Inválido | abc1 |
Error: demasiado corto |
| demasiado tiempo | Inválido | Un valor de 30 caracteres con un dígito. | Error: demasiado largo |
| Longitud válida, sin dígitos | Inválido | amanecer |
Error: dígito necesario |
| En blanco | Inválido | (empty) | Error: requerido |
Tenga en cuenta que cada prueba no válida infringe sólo una regla. Si un valor era demasiado corto y le faltaba un dígito, una prueba aprobada no podría indicarle qué verificación funcionó. Un cheque puede estar roto, mientras que el otro oculta el hecho.
Ejemplo resuelto: entradas no numéricas
La técnica no se limita a rangos de números. Las opciones, categorías y estados discretos también forman particiones. Supongamos que una tienda tiene esta regla:
Requisito: La entrega es gratuita para los miembros Gold, 50 para los Silver y 100 para todos los demás. Los valores de nivel desconocidos son errores.
| Partición | Valor de prueba | Tarifa esperada |
|---|---|---|
| oro | oro |
0 |
| Plata | plata |
50 |
| Sin membresía | (none) | 100 |
| Nivel desconocido | platino |
error |
Aquí, cada opción es su propia partición, ya que cada una debería comportarse de manera diferente. Otras particiones comunes incluyen tipos de archivos, como cargas válidas e inválidas, y grupos basados en resultados, como un préstamo aprobado o rechazado.
Consejo: Piense tanto en los resultados como en los insumos. Si un cálculo puede producir un descuento, ningún descuento o una advertencia, asegúrese de que al menos una prueba alcance cada uno de esos resultados.
Varias entradas a la vez
Con múltiples campos, la cantidad de combinaciones crece rápidamente. Tres campos con cuatro particiones cada uno dan 64 combinaciones. Dos estrategias ayudan:
- Cobertura débil: asegúrese de que cada partición aparezca en al menos una prueba, combinando varios valores válidos por prueba. Para valores no válidos, pruebe uno a la vez para que los errores no se enmascaren entre sí.
- Cobertura basada en reglas: cuando las combinaciones realmente cambian el resultado, como el estado del miembro con el valor del pedido, utilice pruebas de tabla de decisiones para enumerarlas correctamente.
Emparejamiento con análisis de valores límite
La partición le indica qué grupos probar. Dice poco sobre dónde en un grupo a los insectos les gusta esconderse, y muchos se esconden justo en los bordes. Para mostrar esto, escribimos una versión con errores con el clásico error de uno por uno:
def buggy(age):
return 18 < age <= 60 # should be 18 <= age
[buggy(a) for a in (35, 10, 75)] # [True, False, False]
buggy(18) # False
Nuestros valores de partición, 35, 10 y 75, dieron todas las respuestas correctas, por lo que esas pruebas pasarían. Sin embargo, un joven de 18 años es rechazado injustamente. Por eso las dos técnicas van juntas:
| Técnica | elige | Valores para edades de 18 a 60 años. |
|---|---|---|
| Partición de equivalencia | Un valor dentro de cada grupo | 10, 35, 75 |
| Análisis de valor límite | Valores en los bordes de cada grupo. | 17, 18, 60, 61 |
Utilice la partición para encontrar los grupos y luego los límites para probar dónde se encuentran los grupos. En nuestro código, una prueba separada para 17, 18, 60 y 61 pasó la función correcta y detectaría ese error. Nuestra guía de análisis de valores límite cubre esto en su totalidad.
Ventajas y limitaciones
| Ventajas | Limitaciones |
|---|---|
| Reduce enormemente el número de pruebas. | Depende de que las particiones sean correctas |
| Proporciona una cobertura clara y explicable. | Puede pasar por alto errores en los límites |
| No necesita acceso al código | Puede pasar por alto casos especiales ocultos |
| Se aplica temprano, incluso a partir de los requisitos. | No modela bien secuencias o combinaciones. |
El mayor riesgo es una suposición incorrecta. Si el código tiene una regla oculta para un valor específico, es posible que la prueba elegida simplemente no lo alcance. Las pruebas exploratorias y la cobertura del código lo ayudan a encontrar lo que omitieron las particiones.
Errores comunes
- Olvidar particiones no válidas. Probar solo rutas felices deja el manejo de errores sin marcar.
- Prueba de varios valores de una partición. Esto agrega costos sin nueva información.
- Combinando varios valores no válidos en una prueba. Un error puede ocultar otro.
- Saltar límites. Las pruebas de partición por sí solas a menudo pasan por alto errores uno por uno.
- Adivinar las reglas. Si un requisito no está claro, pregunte. ¿60 debería incluir a personas de 60 años y medio?
Conclusión
La partición de equivalencia reemplaza “¿cuántas pruebas debo escribir?” con una pregunta mucho mejor: “¿qué comportamientos existen y he cubierto cada uno de ellos?” Para probarlo, tome un formulario que esté probando hoy y enumere sus particiones en papel, incluidas las no válidas. Agregue límites a continuación. A menudo terminarás con menos pruebas que encuentren más errores.
Preguntas frecuentes
¿Qué es la partición de equivalencia en las pruebas?
Es una técnica de caja negra que divide las entradas en grupos que se espera que se comporten de manera similar. Luego prueba un valor representativo de cada grupo, no todos los valores.
¿Cuál es la diferencia entre la partición de equivalencia y el análisis de valores límite?
La partición elige un valor del interior de cada grupo. El análisis de valores límite prueba los valores en los bordes de esos grupos. Generalmente se usan juntos.
¿Cuántos casos de prueba necesita la partición de equivalencia?
Generalmente al menos uno por partición, tanto válido como no válido. Un campo de rango de edad normalmente necesita entre tres y cinco pruebas.
¿La partición de equivalencia es una caja negra o una caja blanca?
Es una técnica de caja negra, ya que las particiones provienen de requisitos y no necesitan el código. Sin embargo, los desarrolladores también pueden aplicarlo a las pruebas unitarias.
¿Qué son las particiones válidas y no válidas?
Las particiones válidas contienen valores que el sistema debería aceptar. Las particiones no válidas contienen valores que debería rechazar, como números fuera de rango, tipos incorrectos y espacios en blanco.
sigue aprendiendo
¿Necesitas ayuda con pruebas, WordPress o SEO?
Ayudamos a los equipos a enviar mejor software y hacer crecer sus sitios. Cuéntenos en qué está trabajando y le sugeriremos un siguiente paso claro.
Más guías sobre testing, IA y desarrollo moderno
¿Te gustó este artículo? Elige un tema y salta directo a nuestros tutoriales más recientes.
Explicación de las alucinaciones de la IA: por qué los modelos de lenguaje inventan cosas y cómo reducirlas
Se explicaron las alucinaciones de la IA: qué son, por qué los modelos de lenguaje las producen, tipos comunes, cómo reducirlas con conexión a tierr…
Leer artículo →DevOpsExplicación de las variables de entorno: archivos .env, secretos y configuración bien hechos
Variables de entorno explicadas con ejemplos de Python que ejecutamos: leerlas y configurarlas, por qué cada valor es una cadena, archivos .env, her…
Leer artículo →Desarrollo de softwareExplicación de la limitación de velocidad de API: algoritmos, encabezados y manejo de errores 429
La limitación de la tasa de API se explica con una simulación que ejecutamos: depósito de tokens, ventana fija, ventana deslizante, 429 respuestas, …
Leer artículo →Automatización de pruebasBurlarse en Python: unittest.mock, patch y los errores que hacen que las pruebas mientan
Burlarse en Python con unittest.mock, probado: Mock y return_value, side_effect, parches donde se usa un nombre, especificación y autospec, fechas d…
Leer artículo →Pruebas de softwareExplicación de la cobertura del código: cobertura de línea versus sucursal y lo que realmente significa 100%
Cobertura del código explicada con una ejecución real de cobertura.py: cobertura de línea, rama y condición, lectura de un informe, por qué una cobe…
Leer artículo →Bases de datos y SQLDELETE vs TRUNCATE vs DROP en SQL: diferencias, reversión y cuándo usar cada uno
DELETE vs TRUNCATE vs DROP explicado con SQL probado: qué elimina cada uno, reversión, activadores, restablecimiento de identidad, velocidad y en qu…
Leer artículo →Bases de datos y SQLVistas SQL explicadas: cree, use y evite los errores, con ejemplos
Vistas SQL explicadas con consultas que ejecutamos: creación de una vista, resultados en vivo, ocultación de columnas, rendimiento, vistas actualiza…
Leer artículo →Desarrollo de softwareInterfaz TypeScript versus tipo: diferencias reales, probadas con el compilador
Interfaz TypeScript versus tipo, verificado con el compilador real: qué pueden hacer ambos, qué puede hacer solo uno, fusión de declaraciones, exten…
Leer artículo →Desarrollo de softwarePython *args y **kwargs explicados: funciones flexibles con ejemplos claros
Python *args y **kwargs explicados con el código que ejecutamos: empaquetado y desempaquetado, orden de parámetros, argumentos solo de palabras clav…
Leer artículo →Desarrollo de softwareFunciones Lambda de Python: sintaxis, usos reales y cuándo no utilizarlas
Funciones lambda de Python explicadas con el código que ejecutamos: sintaxis, clasificación con clave, mapa y filtro, cierres, trampa de enlace tard…
Leer artículo →Inteligencia artificial¿Qué son los agentes de IA? Cómo funcionan, con un bucle de agente simple que puedes ejecutar
¿Qué son los agentes de IA? Una guía sencilla sobre el bucle del agente, las herramientas, la memoria y las barreras de seguridad, con un pequeño bu…
Leer artículo →DevOpsMonitoreo versus observabilidad: la verdadera diferencia, con registros, métricas y seguimientos
Explicación del monitoreo versus observabilidad: fallas conocidas y desconocidas, registros, métricas y seguimientos, un recorrido por incidentes de…
Leer artículo →DevOpsDocker Volumes versus Bind Mounts: persistir los datos del contenedor de la manera correcta
Se explican los volúmenes de Docker frente a los montajes de enlace: por qué desaparecen los datos del contenedor, volúmenes con nombre, montajes de…
Leer artículo →Automatización de pruebasTDD vs BDD: diferencias clave, una función creada en ambos sentidos y cuándo usar cada una
TDD vs BDD explicado con una característica de descuento construida en ambos sentidos: refactor rojo-verde con el código que ejecutamos, escenarios …
Leer artículo →Pruebas de softwarePruebas de Aceptación de Usuario (UAT): Proceso, Lista de Verificación y Ejemplos Reales
Explicación de las pruebas de aceptación del usuario: quién las ejecuta, en qué se diferencia del control de calidad, un proceso de siete pasos, una…
Leer artículo →Bases de datos y SQLValores NULL de SQL explicados: IS NULL, COALESCE, NULLIF y las trampas que se deben evitar
Los valores NULL de SQL se explican con las consultas que ejecutamos: lógica de tres valores, IS NULL, COALESCE, NULLIF, cómo los agregados, las uni…
Leer artículo →Bases de datos y SQLDeclaración SQL CASE WHEN: sintaxis, ejemplos reales y errores comunes
CASO SQL CUANDO se explicó con las consultas que ejecutamos: formularios simples y buscados, orden de condiciones, pivotes con SUMA, trucos COUNT, c…
Leer artículo →Desarrollo de software¿Qué es JWT? Tokens web JSON explicados con un ejemplo práctico
¿Qué es JWT? JSON Web Tokens explicó: las tres partes, un token creado y manipulado en el código que ejecutamos, JWT vs sesiones, almacenamiento, to…
Leer artículo →Desarrollo de softwareExplicación del bucle de eventos de JavaScript: pila de llamadas, microtareas y temporizadores con ejemplos
El bucle de eventos de JavaScript explicado con el código que ejecutamos: pila de llamadas, colas de tareas y microtareas, por qué setTimeout 0 no e…
Leer artículo →Desarrollo de softwareExplicación de los generadores y el rendimiento de Python: ahorre memoria con ejemplos reales
Los generadores de Python y el rendimiento se explican con el código que ejecutamos: cómo se pausan y reanudan, midieron el ahorro de memoria, canal…
Leer artículo →Inteligencia artificial¿Qué son las incrustaciones? Los vectores y la similitud del coseno se explican de forma sencilla
¿Qué son las incrustaciones? Una guía en lenguaje sencillo sobre vectores, similitud de cosenos y búsqueda semántica, con un pequeño ejemplo que eje…
Leer artículo →DevOpsImplementación azul-verde versus implementación canaria: diferencias, compensaciones y cómo elegir
Explicación de la implementación azul-verde versus canaria: cómo funciona cada uno, costo, riesgo y reversión, agrupación estable de usuarios que pr…
Leer artículo →Automatización de pruebasPruebas inestables: qué las causa y cómo solucionarlas para siempre
Pruebas inestables explicadas con demostraciones que realizamos: las causas principales, cómo confirmar y diagnosticar una, correcciones adecuadas p…
Leer artículo →Pruebas de softwarePruebas de carga frente a pruebas de estrés: diferencias, métricas y ejemplos de k6
Explicación de las pruebas de carga frente a las pruebas de estrés: qué prueba cada una, pruebas de picos y de absorción, las métricas que importan,…
Leer artículo →Pruebas de softwareCaso de prueba frente a escenario de prueba: diferencias clave, ejemplos y cuándo utilizar cada uno
Caso de prueba versus escenario de prueba explicado: definiciones claras, una tabla en paralelo, una función de restablecimiento de contraseña tomad…
Leer artículo →Bases de datos y SQLOptimización de consultas SQL: lea planes de ejecución y corrija consultas lentas, con tiempos
Optimización de consultas SQL probada en un millón de filas: lea planes de ejecución, agregue los índices correctos, corrija filtros no sargables, u…
Leer artículo →Bases de datos y SQLSQL UNION vs UNION ALL: diferencias, ejemplos y rendimiento probado
SQL UNION vs UNION ALL explicado con consultas que ejecutamos: duplicados, las reglas que siguen ambos, un error de datos real, rendimiento medido, …
Leer artículo →Desarrollo de softwareTutorial de JavaScript Fetch API: GET, POST, manejo de errores y tiempos de espera
Un tutorial de JavaScript Fetch API probado en un servidor local: GET y POST, por qué 404 no arroja, un asistente reutilizable, cadenas de consulta,…
Leer artículo →Desarrollo de softwareManejo de archivos Python: lectura, escritura, CSV, JSON y pathlib con ejemplos
El manejo de archivos Python se explica con el código que ejecutamos: modos abiertos, lectura de archivos grandes, CSV, JSON, pathlib, archivos bina…
Leer artículo →Desarrollo de softwareClases y objetos de Python: tutorial de programación orientada a objetos con ejemplos reales
Clases y objetos de Python explicados con el código que ejecutamos: __init__, métodos, atributos de clase versus instancia, herencia, propiedades, m…
Leer artículo →Inteligencia artificial¿Qué es un modelo de lenguaje grande? Cómo funcionan los LLM, explicados sin exageraciones
¿Qué es un modelo de lenguaje grande? Los LLM explicados en lenguaje sencillo: tokens, incrustaciones, atención, entrenamiento, ventanas de temperat…
Leer artículo →DevOpsComandos de Linux para principiantes: la guía esencial de terminal con ejemplos
Comandos de Linux para principiantes, agrupados por tarea: navegación, archivos, visualización de registros, grep, canalizaciones, permisos, proceso…
Leer artículo →Automatización de pruebasSelenium vs Playwright: diferencias clave, comparación de códigos y cuál elegir
Comparación de Selenium vs Playwright: arquitectura, espera, soporte de navegador e idioma, depuración, la misma prueba en ambas herramientas, conse…
Leer artículo →Pruebas de softwarePartición de equivalencia: técnica de diseño de pruebas explicada con ejemplos resueltos
Explicación de la partición de equivalencia: cómo encontrar particiones válidas e inválidas, ejemplos prácticos para edades, contraseñas y cupones, …
Leer artículo →Pruebas de softwareSeveridad vs Prioridad en Pruebas de Software: Diferencias, Matriz y Ejemplos Reales
Explicación de gravedad versus prioridad en las pruebas de software: definiciones claras, una matriz de cuatro vías con ejemplos, escalas de niveles…
Leer artículo →Bases de datos y SQLTutorial de subconsultas SQL: tipos, subconsultas correlacionadas y EXISTENCIAS con ejemplos
Un tutorial de subconsultas SQL con consultas que ejecutamos: subconsultas escalares, IN, FROM y SELECT, subconsultas correlacionadas, EXISTS, la tr…
Leer artículo →Bases de datos y SQLTransacciones SQL y ACID explicados: COMMIT, ROLLBACK y niveles de aislamiento
Transacciones SQL y ACID explicadas con una transferencia bancaria que ejecutamos: COMMIT, ROLLBACK, puntos de guardado, bloqueos, niveles de aislam…
Leer artículo →Desarrollo de softwareGit merge vs rebase: diferencias, ejemplos y cuándo usar cada uno
Git merge vs rebase explicado con salida real del log, una tabla comparativa, la regla de oro del rebase y un flujo de trabajo seguro para equipos.
Leer artículo →Desarrollo de softwareList comprehension en Python: sintaxis, ejemplos y cuándo evitarla
List comprehension en Python explicada: sintaxis, filtros, if-else, bucles anidados, tiempos medidos y cuándo es mejor un bucle for normal.
Leer artículo →