Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Guía de Referencia 6: Control de Calidad (Pruebas)

Estación “CONTROL DE CALIDAD”: una caja-producto entra por una cinta a una máquina inspectora con lupa y palomita, equipada con “assert” y “pytest”; dos salidas, una rampa “PASA” hacia un estante y una rampa “FALLA” hacia un contenedor de rechazo

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án if __name__ == "__main__": de la Guía 5. Sin él, el import arrancaría el menú.

Nota: import inventario funciona sin instalar nada porque inventario.py vive en la misma carpeta que pruebas_inventario.py; Python busca ahí primero, antes que en la biblioteca estándar. Es un mecanismo distinto a los import de módulos como random o json: no hay pip de 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 con assert normales, 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.