Guía de Referencia 6: Control de Calidad (Pruebas)
Fig. 12.2: Control de calidad: toda caja pasa por la estación de pruebas.
Un almacén serio no despacha mercancía sin revisarla (Fig. 12.2). Tu código tampoco debería. Probar es la forma de cambiar una función mañana sin romper otras tres por accidente. Aquí lo haces con assert, que ya viene en Python: primero suelto, para un vistazo, y luego agrupado en funciones que se quedan contigo.
assert: la revisión rápida
assert comprueba que algo que tú das por cierto lo sea de verdad. Si lo es, no pasa nada; si no, el programa se detiene con un AssertionError que te dice dónde falló tu propia suposición.
def crear_producto(id_producto, nombre, precio, stock):
return {
"id": id_producto,
"nombre": nombre,
"precio": precio,
"stock": stock,
}
caja = crear_producto("1", "Tornillos", 5.5, 500)
assert caja["precio"] == 5.5 # pasa en silencio
assert caja["stock"] == 500 # pasa en silencio
assert len(caja) == 4, "Faltan campos en el producto" # mensaje si falla
Es una red de seguridad para tus suposiciones mientras desarrollas. Un detalle: assert está pensado para verificar tu código, no para validar datos del usuario (de hecho, Python puede desactivarlo al ejecutar con la opción -O). Para rechazar entradas inválidas usa raise, como viste en el capítulo de excepciones.
Pruebas que se quedan: funciones probar_
Los assert sueltos sirven para un vistazo. Cuando quieres pruebas que puedas correr una y otra vez, agrúpalas en funciones. Cada función revisa una expectativa y grita si no se cumple. Guarda esto como pruebas_inventario.py junto a tu inventario.py:
from inventario import (agregar_producto, buscar_producto,
eliminar_producto, generar_id)
def probar_agregar() -> None:
inventario = []
agregar_producto(inventario, "Tornillos", 5.5, 500)
assert len(inventario) == 1
assert inventario[0]["id"] == "1"
def probar_buscar_inexistente() -> None:
assert buscar_producto([], "999") is None
def probar_ids_no_se_reciclan() -> None:
inventario = []
agregar_producto(inventario, "Tornillos", 5.5, 500) # ID "1"
agregar_producto(inventario, "Tuercas", 3.0, 200) # ID "2"
inventario = eliminar_producto(inventario, "1")
assert generar_id(inventario) == "3", "generar_id recicló un ID usado"
probar_agregar()
probar_buscar_inexistente()
probar_ids_no_se_reciclan()
print("Todas las pruebas pasaron.")
¡Ojo!: la primera línea, importar
inventario, solo es segura porque el archivo termina con el guardiánif __name__ == "__main__":de la Guía 5. Sin él, elimportarrancaría el menú.
Nota:
import inventariofunciona sin instalar nada porqueinventario.pyvive en la misma carpeta quepruebas_inventario.py; Python busca ahí primero, antes que en la biblioteca estándar. Es un mecanismo distinto a losimportde módulos comorandomojson: no haypipde por medio, solo la ubicación del archivo. Y es justo ese guardián del párrafo anterior el que hace que importarlo sea seguro.
Corre el archivo y una sola línea te dice que todo pasó. El día que toques agregar_producto o generar_id, estas tres funciones te avisan al instante si rompiste algo.
Nota: en el mundo profesional, la herramienta más usada es pytest. No viene en la biblioteca estándar (se instala con
pip install pytest), pero acepta funciones conassertnormales, casi idénticas a las que acabas de escribir. Cuando termines este libro, es el paso natural.
El SGI v1.0 está probado y funcionando. Sigue con Mejoras y Desafíos si quieres llevarlo más lejos.