fix(tests): la espera de arranque del servidor MCP tiene que esperar de verdad - #250
Merged
Merged
Conversation
…de verdad
`test_authenticated_mcp_http_delivers_disposable_capture` cayo CUATRO veces el
2026-08-31, siempre en Windows, con `authority_unavailable`. Entre 1 y 1,5 horas
de suite cada vez, mas el relanzamiento que vuelve a pagarla entera.
NO era aleatorio. El bucle de arranque del fixture tenia dos defectos:
for _ in range(100):
try:
if httpx.get(health, timeout=0.2).status_code == 200: break
except httpx.HTTPError:
time.sleep(0.02) # <- el sleep SOLO aca
1. Sin sleep en la rama de "respondio pero no 200" —el caso normal mientras
arranca— el bucle giraba sus 100 vueltas en milisegundos y se rendia sin
haber esperado nada.
2. El limite estaba en VUELTAS, no en tiempo: el presupuesto real dependia de si
cada intento fallaba rapido o agotaba su timeout. O sea que no habia
presupuesto.
Por que el sintoma mentia: el fallo no aparecia como un error de arranque
legible. El test avanzaba, la llamada MCP fallaba, y `_classify_transport_error`
(backend.py:273) la reportaba como `authority_unavailable`, que es su FALLBACK
para cualquier error de transporte sin clasificar.
`_wait_until_healthy` reemplaza el bucle: limite por TIEMPO, sleep en todos los
caminos, timeout por intento de 1s en vez de 0,2s.
NO es un reintento y hay un test que lo fija: un servidor que nunca levanta
sigue fallando. No repite aserciones ni tolera un fallo persistente — que era el
riesgo de la alternativa que descarte (marker de reintento, ademas de exigir una
dependencia nueva; ninguna de pytest-rerunfailures/flaky/pytest-retry esta
instalada). La otra alternativa, un job aparte no bloqueante, tapa la caida por
completo, que contradice el criterio del PR #249: el chequeo tiene que llegar a
hablar.
Barra roja verificada contra el bucle ORIGINAL: caen exactamente los dos tests
que anclan los defectos y los otros tres pasan, porque ese comportamiento ya
estaba bien.
13/13 en la suite real de hermes, 5/5 en los nuevos, ruff limpio, release-truth
regenerado ANTES de commitear.
Los 8 PRs del dia, los resultados MEDIDOS (perfil destrabado tras 10 dias, PPR-7 volviendo a emitir, corpus 18% -> 96% agrupado, cero claims vivas en tenant NULL), los 9 items que quedan abiertos con su evidencia, y las seis trampas que costaron tiempo hoy — incluida la de release-truth, en la que cai cuatro veces.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
El flaky no era aleatorio
test_authenticated_mcp_http_delivers_disposable_capturecayó cuatro veces el 2026-08-31, siempre en Windows, conauthority_unavailable. Entre 1 y 1,5 horas de suite cada vez, más el relanzamiento que vuelve a pagarla entera.Los dos defectos
Por qué el síntoma mentía
El fallo no aparecía como un error de arranque legible. El test avanzaba, la llamada MCP fallaba, y
_classify_transport_error(backend.py:273) la reportaba comoauthority_unavailable— que es su fallback para cualquier error de transporte sin clasificar. Por eso durante meses se leyó como "ruido de red".Por qué NO un marker de reintento ni un job aparte
pytest-rerunfailures,flakynipytest-retryestá instalada. Y tolera el síntoma en vez de arreglarloEste arreglo no tolera nada: le da al arranque el tiempo que el bucle decía darle y no daba.
Y hay un test que fija que no es un reintento: un servidor que nunca levanta sigue fallando.
Barra roja
Verificada contra el bucle original: caen exactamente los dos tests que anclan los defectos, y los otros tres pasan — porque ese comportamiento ya estaba bien. Un test que fallara con el código viejo y con el nuevo no estaría midiendo el defecto.
13/13 en la suite real de hermes, 5/5 en los nuevos, ruff limpio.