AgentEvalTool/tests/integration/test_intelligent_eval_scan_scheduler.py
sinohqb 775b070bab
All checks were successful
CI / test (push) Successful in 3m48s
feat(intelligent-eval): platform triggers OpenClaw agent as worker (avoid external IM channel)
OpenClaw cron requires a channel (announce->last fail-closed); webchat is a
Control-UI feature, not an addressable channel, and platform-side static
execution would degrade the intelligent eval into a static evaluation.

Solution (plan C): the platform keeps the scan loop and, when the queue has
a pending task, invokes the headless agent:
  docker exec openclaw-eval openclaw agent --agent main \
    -m agenteval-intelligent-worker --json
--deliver defaults to false, so no cron delivery channel is involved. The
worker skill runs unchanged under the OpenClaw agent (LLM decisions +
evaluator/analyst skills). Verified headless invocation returns ok.
2026-08-17 02:37:37 +08:00

81 lines
2.7 KiB
Python

"""Lifespan scan-loop test (v1.1.0 defect fix).
`scan_and_enqueue_tasks` previously had no scheduler — the OpenClaw Worker
wakes every minute but could never pull a task. The lifespan now starts an
asyncio background task that scans executing evals every 60s. This test
verifies that on application startup the scan is actually invoked.
"""
from unittest.mock import MagicMock
from fastapi.testclient import TestClient
def test_lifespan_starts_scan_loop(monkeypatch):
"""Lifespan startup must invoke the intelligent-eval scan loop once."""
import agenteval.intelligent_eval.task_queue as tq
import agenteval.web.app as app_mod
calls: list[int] = []
real_scan = tq.scan_and_enqueue_tasks
def fake_scan(session):
calls.append(1)
return real_scan(session)
# The scan loop calls get_session() to open a DB session; replace it with a
# no-op mock so the test does not touch the real SQLite file.
monkeypatch.setattr(app_mod, "get_session", lambda: MagicMock())
monkeypatch.setattr(tq, "scan_and_enqueue_tasks", fake_scan)
with TestClient(app_mod.app) as client:
assert client.get("/api/health").status_code == 200
# The background task runs immediately (before its first 60s sleep).
assert calls, "scan_and_enqueue_tasks should have been invoked on startup"
def test_trigger_worker_skips_when_no_pending(monkeypatch):
"""No pending task → no docker exec invocation."""
import asyncio
import subprocess
from unittest.mock import MagicMock
import agenteval.web.app as app_mod
calls: list = []
monkeypatch.setattr(app_mod, "_has_pending_task", lambda: False)
def fake_run(cmd, **kwargs):
calls.append(cmd)
return MagicMock(returncode=0, stderr="")
monkeypatch.setattr(subprocess, "run", fake_run)
assert asyncio.run(app_mod._trigger_intelligent_worker()) is False
assert not calls, "should not invoke docker exec when queue is empty"
def test_trigger_worker_calls_docker_exec(monkeypatch):
"""Pending task present → invoke `docker exec openclaw-eval openclaw agent`."""
import asyncio
import subprocess
from unittest.mock import MagicMock
import agenteval.web.app as app_mod
calls: list = []
monkeypatch.setattr(app_mod, "_has_pending_task", lambda: True)
def fake_run(cmd, **kwargs):
calls.append(cmd)
return MagicMock(returncode=0, stderr="")
monkeypatch.setattr(subprocess, "run", fake_run)
assert asyncio.run(app_mod._trigger_intelligent_worker()) is True
assert calls, "docker exec should be invoked"
joined = " ".join(calls[0])
assert "docker" in joined and "openclaw" in joined
assert "agenteval-intelligent-worker" in joined
assert "--agent" in joined and "main" in joined