El análisis de valores límite (BVA) es una técnica de diseño de pruebas de caja negra que concentra los casos de prueba en los bordes de los rangos de entrada — exactamente donde se esconden los bugs de off-by-one como < en lugar de <=. En vez de muestrear cientos de valores intermedios que pasarán todos, el BVA prueba seis valores por rango (min−1, min, min+1, max−1, max, max+1) y atrapa de forma fiable los errores de operadores de comparación que el testing de valores medios nunca encuentra. Esta guía recorre la técnica con ejemplos numéricos, de longitud de cadenas, fechas y tamaños de archivo, más patrones de automatización listos para usar.
TL;DR
- Los bugs se concentran en los límites: prueba en y alrededor de cada borde del rango (min−1, min, min+1, max−1, max, max+1), no en el medio
- Seis valores enfocados por rango reemplazan cientos aleatorios — una de las técnicas de diseño de pruebas con mayor ROI
- Combina BVA con partición de equivalencia y automatiza los valores como tests parametrizados de regresión
Por Qué Importan los Límites
Considera este bug del mundo real de una aplicación bancaria:
Validación de Monto de Transferencia:
- Mínimo: $1.00
- Máximo: $10,000.00
Bug: Transferir exactamente $10,000.00 resultó en error:
"El monto excede el límite máximo"
Causa Raíz: El desarrollador usó "amount < max" en lugar de "amount <= max"
Este bug solo apareció en el valor límite exacto. Probar $5,000 o $9,999 nunca lo habría detectado. Solo probar en y alrededor del límite ($9,999.99, $10,000.00, $10,000.01) revelaría el problema.
«El testing es una habilidad, no solo una lista de verificación. Los testers más efectivos con los que he trabajado combinan un conocimiento profundo del dominio con pensamiento estructurado: pueden predecir dónde fallará el software antes de escribir un solo caso de prueba.» — Yuri Kan, Senior QA Lead
El Principio BVA
Para cualquier rango de entrada con límites, prueba estos valores:
| Posición | Valor a Probar | Por Qué |
|---|---|---|
| Justo Debajo del Mín | mín - 1 | Debería ser rechazado (inválido) |
| Exactamente Mín | mín | Debería ser aceptado (límite válido) |
| Justo Encima del Mín | mín + 1 | Debería ser aceptado (válido) |
| Justo Debajo del Máx | máx - 1 | Debería ser aceptado (válido) |
| Exactamente Máx | máx | Debería ser aceptado (límite válido) |
| Justo Encima del Máx | máx + 1 | Debería ser rechazado (inválido) |
Esto te da 6 casos de prueba en lugar de probar miles de valores al azar.
Ejemplo Básico de BVA: Validación de Edad
Requisito: El campo de edad acepta valores de 18 a 65 (inclusive)
Enfoque de Prueba Tradicional (Ineficiente)
Valores de prueba: 25, 30, 35, 40, 45, 50, 55, 60
Resultado: Todos pasan, pero cobertura limitada
Enfoque BVA (Eficiente)
Valores de prueba:
- 17 (mín - 1) → Esperado: Rechazado ❌
- 18 (mín) → Esperado: Aceptado ✅
- 19 (mín + 1) → Esperado: Aceptado ✅
- 64 (máx - 1) → Esperado: Aceptado ✅
- 65 (máx) → Esperado: Aceptado ✅
- 66 (máx + 1) → Esperado: Rechazado ❌
Resultado: 6 pruebas enfocadas con mayor tasa de detección de defectos
Plantilla de Caso de Prueba BVA
**ID del Caso de Prueba**: TC-BVA-AGE-001
**Característica**: Validación de Edad
**Límite**: 18-65 (inclusive)
| ID Prueba | Valor Entrada | Posición | Resultado Esperado | Resultado Real | Estado |
|-----------|--------------|----------|-------------------|---------------|--------|
| 1 | 17 | mín - 1 | Error: "La edad debe ser 18-65" | [A completar] | |
| 2 | 18 | mín | Aceptado | [A completar] | |
| 3 | 19 | mín + 1 | Aceptado | [A completar] | |
| 4 | 64 | máx - 1 | Aceptado | [A completar] | |
| 5 | 65 | máx | Aceptado | [A completar] | |
| 6 | 66 | máx + 1 | Error: "La edad debe ser 18-65" | [A completar] | |
Tipos de Límites a Probar
1. Rangos Numéricos
Ejemplo: Porcentaje de descuento (0% - 100%)
Valores de Prueba BVA:
- -1% → Inválido
- 0% → Válido (límite)
- 1% → Válido
- 99% → Válido
- 100% → Válido (límite)
- 101% → Inválido
Ejemplo de Código Real:
def apply_discount(price, discount_percent):
# Versión con bug
if discount_percent > 0 and discount_percent < 100: # ❌ Bug: excluye 0 y 100
return price * (1 - discount_percent / 100)
else:
raise ValueError("Descuento inválido")
# BVA detectaría este bug:
apply_discount(100, 0) # ❌ Lanza error (¡debería funcionar!)
apply_discount(100, 100) # ❌ Lanza error (¡debería funcionar!)
# Versión corregida
def apply_discount(price, discount_percent):
if 0 <= discount_percent <= 100: # ✅ Correcto: incluye límites
return price * (1 - discount_percent / 100)
else:
raise ValueError("Descuento inválido")
2. Límites de Longitud de Cadena
Ejemplo: Campo de nombre de usuario (3-20 caracteres)
Valores de Prueba BVA:
- 2 caracteres: "ab" → Inválido
- 3 caracteres: "abc" → Válido (límite mín)
- 4 caracteres: "abcd" → Válido
- 19 caracteres: "abcdefghijklmnopqrs" → Válido
- 20 caracteres: "abcdefghijklmnopqrst" → Válido (límite máx)
- 21 caracteres: "abcdefghijklmnopqrstu" → Inválido
Ejemplo de Automatización:
describe('Validación de Nombre de Usuario - BVA', () => {
test('debería rechazar nombre de usuario con 2 caracteres (mín - 1)', () => {
expect(validateUsername('ab')).toBe(false);
});
test('debería aceptar nombre de usuario con 3 caracteres (mín)', () => {
expect(validateUsername('abc')).toBe(true);
});
test('debería aceptar nombre de usuario con 4 caracteres (mín + 1)', () => {
expect(validateUsername('abcd')).toBe(true);
});
test('debería aceptar nombre de usuario con 19 caracteres (máx - 1)', () => {
expect(validateUsername('a'.repeat(19))).toBe(true);
});
test('debería aceptar nombre de usuario con 20 caracteres (máx)', () => {
expect(validateUsername('a'.repeat(20))).toBe(true);
});
test('debería rechazar nombre de usuario con 21 caracteres (máx + 1)', () => {
expect(validateUsername('a'.repeat(21))).toBe(false);
});
});
3. Límites de Fecha/Hora
Ejemplo: Sistema de reservas (reservas con 1-365 días de anticipación)
Hoy: 2025-10-02
Valores de Prueba BVA:
- Hoy (día 0) → Inválido (debe ser al menos 1 día de anticipación)
- Mañana (día 1) → Válido (límite mín)
- 2 días adelante (día 2) → Válido
- 364 días adelante → Válido
- 365 días adelante → Válido (límite máx)
- 366 días adelante → Inválido
4. Límites de Array/Colección
Ejemplo: Carrito de compras (1-99 artículos)
Valores de Prueba BVA:
- 0 artículos → Inválido (carrito vacío)
- 1 artículo → Válido (límite mín)
- 2 artículos → Válido
- 98 artículos → Válido
- 99 artículos → Válido (límite máx)
- 100 artículos → Inválido (excede límite)
BVA de Dos Puntos vs Tres Puntos
BVA de Dos Puntos (Mínimo)
Prueba solo los valores límite:
Para rango 18-65:
- 18 (mín)
- 65 (máx)
Pros: Enfoque más rápido Contras: Puede perder errores off-by-one
BVA de Tres Puntos (Estándar)
Prueba límite ± 1:
Para rango 18-65:
- 17 (mín - 1)
- 18 (mín)
- 19 (mín + 1)
- 64 (máx - 1)
- 65 (máx)
- 66 (máx + 1)
Pros: Mejor balance de cobertura y eficiencia Contras: Más casos de prueba que dos puntos
Ejemplos del Mundo Real de BVA
Ejemplo 1: Código de Descuento E-commerce
Requisito: Código de descuento válido para pedidos de $50-$500
def apply_discount_code(order_total, code):
if order_total >= 50 and order_total <= 500:
return order_total * 0.9 # 10% de descuento
else:
raise ValueError("El total del pedido debe ser $50-$500 para usar este código")
# Casos de Prueba BVA:
assert raises_error(apply_discount_code(49.99, "SAVE10")) # Justo debajo del mín
assert apply_discount_code(50.00, "SAVE10") == 45.00 # Exactamente mín
assert apply_discount_code(50.01, "SAVE10") == 45.01 # Justo encima del mín
assert apply_discount_code(499.99, "SAVE10") == 449.99 # Justo debajo del máx
assert apply_discount_code(500.00, "SAVE10") == 450.00 # Exactamente máx
assert raises_error(apply_discount_code(500.01, "SAVE10")) # Justo encima del máx
Errores Comunes de BVA
❌ Error 1: Probar Solo Límites Válidos
Mal enfoque:
- Probar edad = 18 ✅
- Probar edad = 65 ✅
- Perder pruebas: 17 ❌, 66 ❌
Solución: Siempre prueba límites inválidos (mín-1, máx+1)
❌ Error 2: Olvidar Tipos de Datos
Para campo numérico 1-100:
- No olvides probar: null, "", "abc", -1, 0.5, 100.5
BVA en Automatización
El Análisis de Valores Límite es ideal para automatización:
import pytest
@pytest.mark.parametrize("age,expected", [
# Debajo del límite mínimo
(17, "Edad inválida"),
# Límite mínimo
(18, "Válido"),
# Justo encima del mínimo
(19, "Válido"),
# Justo debajo del máximo
(64, "Válido"),
# Límite máximo
(65, "Válido"),
# Encima del límite máximo
(66, "Edad inválida"),
])
def test_age_validation_bva(age, expected):
result = validate_age(age)
assert result == expected
Conclusión
El Análisis de Valores Límite es una de las técnicas de diseño de pruebas más efectivas porque:
- Alta Detección de Defectos: Los bugs se agrupan en los límites
- Eficiente: Prueba 6 valores en lugar de cientos
- Sistemático: Sin conjeturas, valores de prueba claros
- Automatizable: Perfecto para suites de regresión
- Basado en Riesgos: Se enfoca en áreas de alto riesgo
BVA funciona mejor cuando se combina con Particionamiento de Equivalencia para una cobertura de pruebas completa.
Recuerda la regla de oro: Si tiene un límite, pruébalo en los bordes, no solo en el medio.
Ver También
- Pruebas de Caja Negra - Contexto fundamental para BVA
- Técnicas de Diseño de Casos de Prueba - Guía completa de técnicas
- Reportes de Bugs que Encantan a los Desarrolladores - Documenta bugs de límites efectivamente
- Estrategia de Automatización de Pruebas - Automatiza pruebas BVA
- Testing Exploratorio - Complementa BVA con exploración
Recursos Oficiales
FAQ
¿Qué es el análisis de valores límite en testing? El análisis de valores límite (BVA) es una técnica de diseño de pruebas de caja negra que prueba los valores en y alrededor de los bordes de los rangos de entrada, porque los defectos se concentran ahí — típicamente errores de off-by-one como usar < en lugar de <=. Para un rango se prueban min-1, min, min+1, max-1, max y max+1: seis casos enfocados en vez de cientos aleatorios.
¿Cuál es la diferencia entre BVA de dos puntos y de tres puntos? El BVA de dos puntos prueba solo los valores límite en sí (min y max): rápido, pero puede pasar por alto errores de off-by-one. El de tres puntos añade los valores justo dentro y fuera de cada límite (min-1, min+1, max-1, max+1), el equilibrio estándar entre cobertura y esfuerzo. El BVA robusto añade inválidos extremos, null, vacío y tipos de datos incorrectos.
¿Qué valores deberías probar para un rango como 18 a 65? Prueba 17 (justo bajo el mínimo, esperando rechazo), 18 (mínimo, aceptación), 19 (justo sobre el mínimo, aceptación), 64 (justo bajo el máximo, aceptación), 65 (máximo, aceptación) y 66 (justo sobre el máximo, rechazo). Estos seis valores atrapan los bugs de operadores de comparación que valores medios como 40 nunca expondrían.
¿Cuándo no es útil el análisis de valores límite? El BVA necesita rangos ordenados para funcionar. Omítelo en campos de texto libre sin límites de longitud, elecciones binarias como checkboxes, conjuntos sin orden como listas de países y entradas puramente cualitativas. Para esos casos usa partición de equivalencia, tablas de decisión o testing exploratorio — y combina BVA con partición de equivalencia donde sí existan rangos.
