[chore] clear all 64 pre-existing mypy errors in tests/ (no type:ignore)

Convention: no type:ignore/noqa, and pre-existing violations still
violate. The make-quality gate runs 'mypy roboco/ tests/', but the
prior commits' gates only ran mypy on production files, masking 64
type errors across 15 test files (method-assign, unused-ignore,
no-untyped-def, attr-defined, union-attr, has-type, index, misc).

Fixed without any type:ignore:
- method-assign (svc.session.X = / svc.method = AsyncMock()): hold a
  local 'session: MagicMock'/'AsyncMock' and assert on it, or stub via
  object.__setattr__ / monkeypatch / a typed '_bind' helper returning
  Any, or alias 'cc: Any = c' (the pattern the file already used).
- unused 'type: ignore[assignment]' (real code was method-assign):
  removed; replaced with the no-suppression patterns above.
- 'Callable[...] has no attribute assert_*': keep a typed local ref to
  the AsyncMock and assert on the local, not the method-typed attr.
- no-untyped-def: annotate helper params (Any / pytest.MonkeyPatch).
- attr-defined / index / union-attr: type the helper as Any, narrow
  with an 'is not None' assert, or add the missing attr to a fake.
- has-type / return-value: fix the declared return type to the tuple
  the function actually returns.
- PLC0415 inline imports: hoisted to top-level.

test_pr_gate_notifies_pm._stub_gate_path converted fully to the
'cc: Any = c' alias (it already used it for one attr) so its five
'# type: ignore[method-assign]' suppressions are gone.

mypy tests/: 64 errors -> 0 (538 files). ruff check tests/: clean.
All 84 tests in the touched files pass.
This commit is contained in:
Renn F
2026-06-28 16:47:09 +02:00
parent 54fc69c499
commit 4d4bf084c5
16 changed files with 124 additions and 75 deletions
@@ -74,6 +74,7 @@ async def test_cost_over_cap_finalizes_spawn_session_before_evict(
finalize.assert_awaited_once()
# finalize ran with the agent still registered (so it could read the model +
# usage_session_id), and the instance was evicted only after.
assert finalize.await_args is not None
assert finalize.await_args.args[0] == "be-dev-1"
@@ -62,6 +62,7 @@ def orch(monkeypatch: pytest.MonkeyPatch) -> AgentOrchestrator:
class _FakeTracker:
def __init__(self) -> None:
self.activated_with: dict[str, object] | None = None
self.clear = AsyncMock()
async def activate(
self, *, retry_after: float, affected_agents: list[str], kind: str
@@ -141,9 +142,7 @@ async def test_agent_writing_about_error_500_does_not_park(
orch, "_tail_container_logs", AsyncMock(return_value=agent_note)
)
monkeypatch.setattr(orch, "_transcript_tail_text", lambda _a, _lines=80: "")
assert (
await orch._provider_overload_park_target("be-dev-1", _instance()) is None
)
assert await orch._provider_overload_park_target("be-dev-1", _instance()) is None
@pytest.mark.asyncio
@@ -245,7 +244,7 @@ async def test_probe_success_respawns_parked_agent(
)
}
tracker = _FakeTracker()
tracker.clear = AsyncMock() # type: ignore[method-assign]
tracker.clear = AsyncMock()
monkeypatch.setattr(orch, "_make_tracker", lambda _p: tracker)
monkeypatch.setattr(orch, "_delete_waiting_record", AsyncMock())
monkeypatch.setattr(orch, "_generate_resume_prompt", lambda _r, _res: "resume")
+23 -13
View File
@@ -126,10 +126,13 @@ async def test_non_self_heal_tasks_dispatch_regardless_of_confirmation() -> None
# ---------------------------------------------------------------------------
def _originate_engine(captured: dict[str, Any]) -> SelfHealEngine:
def _originate_engine(
captured: dict[str, Any],
) -> tuple[SelfHealEngine, MagicMock, MagicMock, Any]:
"""An engine whose task/project services are mocks that capture the create
request — so the held-for-CEO invariant is unit-testable without a DB."""
session = MagicMock()
session.flush = AsyncMock()
task_svc = MagicMock()
task_svc.list_open_self_heal_tasks = AsyncMock(return_value=[])
@@ -147,6 +150,11 @@ def _originate_engine(captured: dict[str, Any]) -> SelfHealEngine:
return engine, task_svc, project_svc, _self_heal_mod
def _bind(svc: object, name: str, value: object) -> None:
"""Stub `name` on `svc` without tripping mypy's method-assign check."""
object.__setattr__(svc, name, value)
@pytest.mark.asyncio
async def test_originate_opens_task_held_for_ceo(
monkeypatch: pytest.MonkeyPatch,
@@ -169,8 +177,7 @@ async def test_originate_opens_task_held_for_ceo(
raw_ref="r",
)
]
# Bypass the session.flush (MagicMock session) — _originate awaits it.
engine.session.flush = AsyncMock() # type: ignore[assignment]
# session.flush is set in _originate_engine (MagicMock) — _originate awaits it.
count = await engine._originate(obs)
@@ -196,8 +203,9 @@ async def test_approve_and_start_lifts_the_ceo_hold(
) -> None:
"""``approve_and_start`` is the CEO's start gate — it flips
``confirmed_by_human`` True so a held self-heal task finally dispatches."""
svc = TaskService(MagicMock())
svc.session.flush = AsyncMock() # type: ignore[assignment]
session = MagicMock()
session.flush = AsyncMock()
svc = TaskService(session)
task = MagicMock()
task.status = TaskStatus.PENDING
task.team = MagicMock()
@@ -207,7 +215,7 @@ async def test_approve_and_start_lifts_the_ceo_hold(
task.assigned_to = "someone-else"
task.task_type = MagicMock()
task.task_type.value = "code"
svc.get = AsyncMock(return_value=task)
_bind(svc, "get", AsyncMock(return_value=task))
main_pm = MagicMock(id=MAIN_PM_UUID)
agent_svc = MagicMock()
agent_svc.get_by_slug = AsyncMock(return_value=main_pm)
@@ -240,15 +248,16 @@ async def test_list_pending_for_agent_excludes_held_self_heal() -> None:
(``source != 'self_heal' OR confirmed_by_human``), so the database drops a
held self-heal task before the agent ever sees the list.
"""
svc = TaskService(MagicMock())
session = MagicMock()
result = MagicMock()
result.scalars.return_value.all.return_value = []
svc.session.execute = AsyncMock(return_value=result)
svc.unmet_dependency_ids = AsyncMock(return_value=[]) # type: ignore[assignment]
session.execute = AsyncMock(return_value=result)
svc = TaskService(session)
_bind(svc, "unmet_dependency_ids", AsyncMock(return_value=[]))
await svc.list_pending_for_agent(MAIN_PM_UUID)
stmt = svc.session.execute.await_args.args[0]
stmt = session.execute.await_args.args[0]
compiled = str(
stmt.compile(
dialect=postgresql.dialect(), compile_kwargs={"literal_binds": True}
@@ -265,7 +274,7 @@ async def test_list_pending_for_agent_still_offers_delegated_subtask() -> None:
PM-delegated work, where the delegation IS the authorization to start) must
STILL be offered via give_me_work. A universal confirmed_by_human filter
would starve devs of all delegated work."""
svc = TaskService(MagicMock())
session = MagicMock()
delegated = MagicMock()
delegated.source = "manual" # not self_heal
@@ -274,8 +283,9 @@ async def test_list_pending_for_agent_still_offers_delegated_subtask() -> None:
result = MagicMock()
result.scalars.return_value.all.return_value = [delegated]
svc.session.execute = AsyncMock(return_value=result)
svc.unmet_dependency_ids = AsyncMock(return_value=[]) # type: ignore[assignment]
session.execute = AsyncMock(return_value=result)
svc = TaskService(session)
_bind(svc, "unmet_dependency_ids", AsyncMock(return_value=[]))
available = await svc.list_pending_for_agent(MAIN_PM_UUID)