Lección 38 de 45 · Calidad y depuración

Pruebas automáticas

Una prueba automática convierte una expectativa sobre tu programa en código que puede comprobarse cada vez que haces un cambio.

TestingExpectativa antes del arregloLímites
Índice · Lección 38/45
Una prueba responde una pregunta concreta, no intenta demostrar que “todo funciona”

En vez de ejecutar el programa y mirar manualmente la salida, escribes una situación y el resultado que debería producir. Si deja de cumplirse, la prueba falla de forma visible.

Para empezar basta una rutina de tres pasos: prepara → ejecuta → comprueba.

Evidencia de aprendizaje

Escribir primero una expectativa que exponga un caso límite y usarla después para localizar el bug.

Separa mentalmente el caso, la acción y la expectativa

Una prueba pequeña debería poder explicarse en una frase
def aplicar_descuento(precio, porcentaje):
    return precio * (1 - porcentaje / 100)

precio = 100
resultado = aplicar_descuento(precio, 20)
assert resultado == 80

El caso es «precio 100 y descuento 20%». La acción es llamar a la función. La expectativa es 80. Si cambias la implementación y ya no devuelve 80, assert señala la diferencia.

Los límites merecen una prueba propia porque concentran decisiones

El 18 decide exactamente dónde cambia la respuesta
def es_mayor_de_edad(edad):
    return edad >= 18

assert es_mayor_de_edad(17) is False
assert es_mayor_de_edad(18) is True
assert es_mayor_de_edad(19) is True

Probar solo 25 confirmaría un caso fácil. Los valores 17, 18 y 19 rodean la frontera y ayudan a detectar errores como escribir > cuando debía ser >=.

Regla práctica: cuando una condición contiene un límite, prueba justo antes, exactamente en el límite y justo después.

Cuando corriges un bug, conserva una prueba que recuerde ese bug

Si un usuario descubre que una entrada concreta rompe el programa, esa entrada es un excelente caso de prueba. Tras arreglarla, la prueba evita que una modificación futura reintroduzca el mismo fallo.

No adaptes la expectativa para que una implementación equivocada “pase”. Una prueba debe describir el comportamiento deseado, no justificar el resultado actual.

Escribe la pregunta antes de arreglar la respuesta

La función tiene un bug en el límite. En testing, el primer movimiento no es tocar la función: es escribir un caso que haga visible el comportamiento que esperas.

Fase 1 · añade la prueba que falta

Añade el caso (18, True). No arregles todavía la función. Queremos ver una prueba fallando.

Salida esperada
3 casos
2 correctos
test_primero.py
La salida aparecerá aquí.

Necesito una pista
  • Añade (18, True) a la lista de casos.
  • Que solo 2 de 3 sean correctos es el resultado deseado en esta fase: has expuesto el bug.
Ver una solución razonada
def es_mayor_de_edad(edad):
    return edad > 18

casos = [(17, False), (18, True), (19, True)]
aciertos = sum(es_mayor_de_edad(edad) is esperado for edad, esperado in casos)
print(len(casos), "casos")
print(aciertos, "correctos")

Fase 2 · deja que la prueba guíe el arreglo

Ahora sí: cambia la implementación mínima para que las tres expectativas se cumplan.

Salida esperada
3 pruebas superadas
arreglo.py
La salida aparecerá aquí.

Necesito una pista
  • La prueba que falla te dice exactamente qué valor está mal: 18.
Ver una solución razonada
def es_mayor_de_edad(edad):
    return edad >= 18

casos = [(17, False), (18, True), (19, True)]
aciertos = sum(es_mayor_de_edad(edad) is esperado for edad, esperado in casos)
print(aciertos, "pruebas superadas")

Fase 3 · escribe asserts reales

Ahora usa la herramienta real. El segundo assert expresa una expectativa incorrecta: ejecútalo, observa AssertionError y corrige únicamente esa expectativa.

Salida esperada
3 asserts superados
asserts_reales.py
La salida aparecerá aquí.

Necesito una pista
  • Un assert no imprime un resultado cuando se cumple.
  • Si la expresión es falsa, Python lanza AssertionError. El límite de 18 debe ser verdadero.
Ver una solución razonada
def es_mayor_de_edad(edad):
    return edad >= 18

assert es_mayor_de_edad(17) is False
assert es_mayor_de_edad(18) is True
assert es_mayor_de_edad(19) is True
print("3 asserts superados")

Una suite útil crece alrededor del comportamiento, no del número de tests

  • Empieza por un caso normal que explique la regla.
  • Añade límites donde cambian las decisiones.
  • Convierte bugs reales en pruebas de regresión.
Puedes avanzar cuando...

puedes escribir una expectativa antes de tocar la implementación y explicar qué comportamiento concreto protege esa prueba.