pytest sale con 4 y 5 sin tests y un hook lo convierte en PASS
Un harness de agentes open source daba por buenos los cambios que no ejecutaban ni un test: leía los códigos 4 y 5 de pytest como un 0 y escribía PASS.
Un mantenedor de un harness de agentes open source ha destapado un fallo suyo que da bastante grima: su sistema de verificación daba por buenos cambios que no llegaban a ejecutar ni un test. pytest devuelve el código de salida 4 cuando la ruta que le pasas no existe, y 5 cuando una expresión -k no recoge ninguna prueba. Nunca devuelve 0. El hook del harness leyó esos dos casos como un cero y escribió PASS en el registro.
El montaje es el típico de un bucle de agente con paso de verificación: cada ruta modificada tiene su comando de test en una tabla y, cuando el comando termina, un hook lee el payload de la herramienta y apunta PASS o FAIL en un libro de registro. Con el libro en verde, el agente puede dar la tarea por terminada. Tres filas de esa tabla apuntaban a ficheros de test que se habían dividido en ficheros hermanos, así que las rutas ya no existían y pytest no llegaba a recoger nada.
Dos maneras de colar un verde
Falló por dos sitios a la vez. El agente leía el "no tests ran" de stdout como un aprobado, y el hook traducía el código de salida así:
EXIT_CODE=$(echo "$INPUT" | jq -r '.tool_response.exit_code // 0')
Cuando el payload no traía el campo, el valor por defecto de jq lo convertía en 0 y la línea siguiente escribía PASS. El autor señala que justo debajo hay un comentario que avisa del caso de un exit code ausente para otro evento distinto. El default se quedó ahí igual.
El arreglo
La corrección que ha presentado parte de una regla simple: ausente no es cero. Si falta el código de salida, el registro apunta FAIL con un motivo, en lugar de asumir que todo ha ido bien. Además, la matriz incluye ahora una prueba que falla cuando alguna de sus filas no recoge ningún test.
El interés está en el patrón, no en el caso concreto: cualquier verificación que ante un dato que falta se decanta por el lado permisivo acaba aprobando trabajo que nadie ha comprobado. El mantenedor lo deja como pregunta a la comunidad de CI: el "no tests collected" como rojo por defecto, ¿lo pone él o lo decide quien envuelve a pytest?

