Volver a la wiki

Caché compartida entre workers de pytest-xdist causaba tests no deterministas

Descripción

Cambio de caché en tests: Redis → LocMemCache. Soluciona una clase latente de tests no deterministas causada por cache.clear() en un worker borrando los contadores de otro cuando pytest-xdist reparte ficheros a procesos paralelos.

El Problema

Síntomas observados

En el PR #359 (04-08-2026), tras añadir tests/api/test_signup_gate.py:

Root cause

En config/settings/test.py, la caché apuntaba a una instancia Redis compartida:

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": os.getenv("REDIS_URL", "redis://localhost:6379/1"),
        "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
    }
}

Problema: Cuatro ficheros de tests hacen cache.clear():

  1. tests/middleware/test_rate_limit_middleware.py (rate limit).
  2. tests/ui/test_ui_prefs.py (UI preferences).
  3. tests/monitoring/test_ratelimit_hygiene.py (monitoring).
  4. tests/core/test_auth_gate.py (auth).

Cuando pytest-xdist con --dist=loadfile reparte estos ficheros a workers paralelos:

Timing no determinista

La víctima del cache.clear() cambia según el orden de reparto del scheduler de pytest-xdist:

Por eso el mismo run local funciona, pero en CI falla aleatoriamente.

La Solución

Cambiar en config/settings/test.py:

# ANTES: Redis compartida
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": os.getenv("REDIS_URL", "redis://localhost:6379/1"),
        ...
    }
}

# AHORA: LocMemCache aislada por worker
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
        "LOCATION": "crearack-tests",
    }
}

Por qué LocMemCache

Side effects

✅ Ninguno visible. Los contadores de rate limit ahora son fiables porque cada worker tiene el suyo.

⚠️ Nota: En PROD, CACHES sigue usando Redis (no cambia, este fix es solo para tests).

Validación

Reproducción local (con Redis real):

# ANTES de este fix:
pytest tests/api/test_signup_gate.py tests/middleware/test_rate_limit_middleware.py \
    --dist=loadfile -n4 -v

# Resultado: FALLA 3/3 (siempre, porque redis/1 está compartida)

# DESPUÉS:
# (con LocMemCache en test.py)
# Resultado: VERDE 3/3

Citado en commit: “Reproducido 3/3 en local con Redis (cae test_upload_mib_429; en CI cayo test_distinct_paths_independent - misma causa, victima segun timing) y verde 3/3 con LocMemCache.”

Archivos afectados

Véase también

Subir