Boundary Value Analysis: Encontrando Bugs en los Límites es una disciplina crítica en el aseguramiento de calidad de software moderno. According to NIST, software bugs cost the US economy $59.5 billion annually, with about 80% preventable through better testing (NIST Software Testing Study). According to research by Capers Jones, finding and fixing a defect after deployment costs 10-100x more than finding it during design (Capers Jones Software Engineering Best Practices). Esta guía cubre enfoques prácticos que los equipos de QA pueden aplicar de inmediato: desde conceptos básicos y herramientas hasta patrones de implementación del mundo real. Ya sea que estés desarrollando habilidades en esta área o mejorando un proceso existente, encontrarás técnicas accionables respaldadas por experiencia de la industria. El objetivo no es solo la comprensión teórica, sino un framework funcional que puedas adaptar al contexto de tu equipo, stack tecnológico y objetivos de calidad.

TL;DR

  • Prueba temprano y seguido — el costo de corregir defectos crece exponencialmente después del despliegue
  • El testing basado en riesgo garantiza que las áreas de mayor impacto reciban más atención de testing
  • Los buenos informes de bug con pasos de reproducción y comportamiento esperado/real aceleran los tiempos de corrección

Ideal para: Ingenieros QA construyendo o mejorando procesos de testing Omitir si: Equipos con suites de prueba completamente automatizadas y maduras

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ónValor a ProbarPor Qué
Justo Debajo del Mínmín - 1Debería ser rechazado (inválido)
Exactamente MínmínDebería ser aceptado (límite válido)
Justo Encima del Mínmín + 1Debería ser aceptado (válido)
Justo Debajo del Máxmáx - 1Debería ser aceptado (válido)
Exactamente MáxmáxDebería ser aceptado (límite válido)
Justo Encima del Máxmáx + 1Deberí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:

  1. Alta Detección de Defectos: Los bugs se agrupan en los límites
  2. Eficiente: Prueba 6 valores en lugar de cientos
  3. Sistemático: Sin conjeturas, valores de prueba claros
  4. Automatizable: Perfecto para suites de regresión
  5. 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

Recursos Oficiales

FAQ

¿Cuál es la diferencia entre verificación y validación? La verificación comprueba que construiste el producto correctamente (cumple las especificaciones). La validación comprueba que construiste el producto correcto (cumple las necesidades del usuario).

¿Cuándo deberías dejar de hacer testing? Deja de hacer testing cuando: el riesgo se ha reducido a niveles aceptables, las restricciones de tiempo/presupuesto lo requieren, o se cumplen los criterios de salida definidos (p.ej., 95% de cobertura, cero defectos críticos).

¿Qué hace bueno a un informe de bug? Un buen informe de bug incluye: pasos de reproducción precisos, comportamiento real vs esperado, detalles del entorno (SO, navegador, versión), clasificación de severidad y si es posible, un caso de reproducción mínimo.

¿Cómo priorizas el testing cuando el tiempo es limitado? Usa testing basado en riesgo: identifica las áreas de mayor riesgo (código nuevo, lógica compleja, funciones orientadas al cliente) y pruébalas primero, documentando lo que se omitió.