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.
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
def aplicar_descuento(precio, porcentaje):
return precio * (1 - porcentaje / 100)
precio = 100
resultado = aplicar_descuento(precio, 20)
assert resultado == 80El 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
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 TrueProbar 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.
3 casos 2 correctos
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.
3 pruebas superadas
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.
3 asserts superados
La salida aparecerá aquí.
Necesito una pista
- Un
assertno 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 escribir una expectativa antes de tocar la implementación y explicar qué comportamiento concreto protege esa prueba.