BookinglyTech News
Software

Tres capas de pruebas para el código Python que genera la IA

Un desarrollador de telemetría combina Hypothesis, instantáneas de esquema con Pydantic y mutmut para cazar los fallos que la revisión humana deja pasar en el código escrito por asistentes.

3 min de lecturaDev.to0 vistas

Un desarrollador que trabaja con datos de sensores y telemetría ha publicado el montaje que usa para no fiarse del código Python que le devuelven los asistentes: pruebas basadas en propiedades con Hypothesis, instantáneas del esquema JSON de los modelos Pydantic y pruebas de mutación con mutmut, estas últimas solo sobre módulos críticos y en ejecución nocturna. La idea de fondo es que los tests que escribe el propio modelo comprueban lo mismo que el código, así que pasan por los mismos motivos por los que ese código puede estar mal.

El fallo que se cuela entre los tests

El caso típico es una función que convierte lecturas de potencia a vatios usando Decimal y un diccionario de factores. La versión correcta y la incorrecta son casi idénticas: un float donde debería ir un Decimal, una comprobación de negativos que desaparece en un refactor, un "kw" en minúsculas que no está en la tabla. Tres valores escogidos a mano no detectan nada de eso; las propiedades sí. Que una unidad mayor nunca devuelva un valor menor, que la conversión a kW y de vuelta sea exacta, que una lectura negativa lance ValueError. El autor las escribe él, no el asistente, y ahí está el punto: codifican lo que un humano cree que tiene que cumplirse, al margen de lo que haya generado el modelo.

Contratos congelados y mutantes

La segunda capa guarda el JSON schema de cada modelo Pydantic que cruza una frontera de servicio. Si el esquema cambia sin querer —un entero que pasa a float, un campo opcional que pasa a obligatorio— la comparación rompe en integración continua. Si el cambio es deliberado, se actualiza la instantánea en el mismo pull request y el diff deja la modificación de contrato a la vista del revisor.

La tercera son las pruebas de mutación con mutmut, que alteran el código de formas pequeñas y comprueban si algún test se cae. Un mutante que sobrevive señala lógica sin cubrir, diga lo que diga el informe de cobertura. Como es lento, no va en cada PR: se limita a unos pocos módulos y se lanza de noche. Los supervivientes acaban en el backlog como huecos de pruebas.

Para que esto no frene el día a día, usa perfiles de Hypothesis: 50 ejemplos en local y 300 en CI. El flujo de GitHub Actions instala dependencias y ejecuta pytest con el perfil de integración.

Lo que no arregla

El autor lo dice sin adornos: esto no detecta una arquitectura equivocada. Una función bien probada en el sitio incorrecto sigue estando en el sitio incorrecto, y eso necesita a un revisor con criterio. Tampoco sale gratis. Escribir buenas propiedades cuesta, y las primeras tardan más que el código al que protegen. Hypothesis añade tiempo de CI, segundos por propiedad con 300 ejemplos, aunque con fixtures pesadas la cosa cambia.

Su recomendación es acotar el alcance: elegir dos o tres módulos donde un número mal calculado cueste dinero o seguridad, escribir a mano entre tres y cinco propiedades por módulo, congelar los esquemas que cruzan servicios y dejar la mutación para la noche. A eso suma un fichero de reglas en el repositorio que el asistente lea, con instrucciones como usar Decimal para potencia y dinero o no tocar nada bajo el directorio de instantáneas. No sustituye a las pruebas, pero reduce las veces que fallan.