Private
Public Access
0
0

test(ai_client): rename send_result to send in 22 remaining test files

Batch rename of 22 test files. 62 references renamed total.

The full test suite is now GREEN again, matching the pre-rename baseline
from Task 1.1. Pure mechanical rename. No behavior change.

Files affected: test_ai_cache_tracking, test_ai_client_cli,
test_ai_client_result, test_api_events, test_context_pruner,
test_deepseek_provider, test_gemini_cli_* (3 files), test_gui2_mcp,
test_headless_* (2 files), test_live_gui_integration_v2,
test_orchestration_logic, test_phase6_engine, test_rag_integration,
test_run_worker_lifecycle_abort, test_spawn_interception_v2,
test_symbol_parsing, test_tier4_interceptor, test_tiered_aggregation,
test_token_usage.

Note: spec estimated 24 files; actual is 22 (test_deprecation_warnings
no longer exists, and 1 fewer file than spec's list).

Refs: conductor/tracks/send_result_to_send_20260616/
This commit is contained in:
2026-06-17 00:38:29 -04:00
parent 2f45bc4d68
commit ada9617308
23 changed files with 109 additions and 56 deletions
+53
View File
@@ -0,0 +1,53 @@
"""Apply the Phase 4 batch rename to all remaining test files."""
from __future__ import annotations
import sys
from pathlib import Path
FILES = [
"tests/test_ai_cache_tracking.py",
"tests/test_ai_client_cli.py",
"tests/test_ai_client_result.py",
"tests/test_api_events.py",
"tests/test_context_pruner.py",
"tests/test_deepseek_provider.py",
"tests/test_gemini_cli_edge_cases.py",
"tests/test_gemini_cli_integration.py",
"tests/test_gemini_cli_parity_regression.py",
"tests/test_gui2_mcp.py",
"tests/test_headless_service.py",
"tests/test_headless_verification.py",
"tests/test_live_gui_integration_v2.py",
"tests/test_orchestration_logic.py",
"tests/test_phase6_engine.py",
"tests/test_rag_integration.py",
"tests/test_run_worker_lifecycle_abort.py",
"tests/test_spawn_interception_v2.py",
"tests/test_symbol_parsing.py",
"tests/test_tier4_interceptor.py",
"tests/test_tiered_aggregation.py",
"tests/test_token_usage.py",
]
def main() -> int:
total_before = 0
total_renamed = 0
for rel in FILES:
p = Path(rel)
with p.open("r", encoding="utf-8", newline="") as f:
content = f.read()
before = content.count("send_result")
new_content = content.replace("send_result", "send")
with p.open("w", encoding="utf-8", newline="") as f:
f.write(new_content)
remaining = new_content.count("send_result")
print(f"{rel}: {before} -> {before - remaining} (remaining={remaining})")
total_before += before
total_renamed += before - remaining
print(f"Total: renamed {total_renamed} of {total_before} occurrences")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+1 -1
View File
@@ -45,7 +45,7 @@ def test_gemini_cache_tracking() -> None:
mock_client.caches.list.return_value = [MagicMock(size_bytes=5000)]
# Act
result = ai_client.send_result(
result = ai_client.send(
md_content="Some long context that triggers caching",
user_message="Hello",
file_items=file_items
+1 -1
View File
@@ -20,7 +20,7 @@ def test_ai_client_send_gemini_cli() -> None:
MockAdapterClass.return_value = mock_adapter_instance
ai_client._gemini_cli_adapter = mock_adapter_instance
with patch.object(ai_client.events, "emit") as mock_emit:
result = ai_client.send_result(
result = ai_client.send(
md_content="<context></context>",
user_message=test_message,
base_dir=".",
+8 -8
View File
@@ -4,40 +4,40 @@ from src import ai_client
from src.result_types import Result, ErrorInfo, ErrorKind
def test_send_result_public_api_returns_result() -> None:
def test_send_public_api_returns_result() -> None:
with patch.object(ai_client, "set_provider"):
with patch.object(ai_client, "_send_gemini", return_value=Result(data="hello")) as mock_send:
r = ai_client.send_result("system", "user")
r = ai_client.send("system", "user")
assert isinstance(r, Result)
assert r.ok
assert r.data == "hello"
def test_send_result_does_not_emit_deprecation() -> None:
def test_send_does_not_emit_deprecation() -> None:
import warnings
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
with patch.object(ai_client, "set_provider"):
with patch.object(ai_client, "_send_gemini", return_value=Result(data="hi")):
r = ai_client.send_result("system", "user")
r = ai_client.send("system", "user")
assert r.ok and r.data == "hi"
assert not any(issubclass(x.category, DeprecationWarning) for x in w)
def test_send_result_preserves_errors() -> None:
def test_send_preserves_errors() -> None:
err = ErrorInfo(kind=ErrorKind.RATE_LIMIT, message="slow down", source="test")
with patch.object(ai_client, "set_provider"):
with patch.object(ai_client, "_send_gemini", return_value=Result(data="", errors=[err])):
r = ai_client.send_result("system", "user")
r = ai_client.send("system", "user")
assert not r.ok
assert r.errors == [err]
def test_send_result_returns_empty_data_with_error_on_auth_failure() -> None:
def test_send_returns_empty_data_with_error_on_auth_failure() -> None:
err = ErrorInfo(kind=ErrorKind.AUTH, message="bad key", source="test")
with patch.object(ai_client, "set_provider"):
with patch.object(ai_client, "_send_gemini", return_value=Result(data="", errors=[err])):
r = ai_client.send_result("system", "user")
r = ai_client.send("system", "user")
assert not r.ok
assert r.data == ""
+2 -2
View File
@@ -61,7 +61,7 @@ def test_send_emits_events_proper() -> None:
ai_client.events.on("request_start", start_callback)
ai_client.events.on("response_received", response_callback)
ai_client.set_provider("gemini", "gemini-2.5-flash-lite")
result = ai_client.send_result("context", "message", )
result = ai_client.send("context", "message", )
assert result.ok
assert start_callback.called
assert response_callback.called
@@ -105,6 +105,6 @@ def test_send_emits_tool_events() -> None:
tool_callback(*args, **kwargs)
ai_client.events.on("tool_execution", debug_tool)
result = ai_client.send_result("context", "message", enable_tools=True)
result = ai_client.send("context", "message", enable_tools=True)
assert result.ok
assert tool_callback.call_count >= 1
+1 -1
View File
@@ -105,7 +105,7 @@ def test_token_reduction_logging(capsys):
with pytest.MonkeyPatch().context() as m:
m.setattr("builtins.open", lambda f, *args, **kwargs: type('obj', (object,), {'read': lambda s: code, '__enter__': lambda s: s, '__exit__': lambda s, *a: None})())
m.setattr("pathlib.Path.exists", lambda s: True)
m.setattr("src.ai_client.send_result", lambda **kwargs: Result(data="DONE"))
m.setattr("src.ai_client.send", lambda **kwargs: Result(data="DONE"))
run_worker_lifecycle(ticket, context, context_files=["test.py"])
+6 -6
View File
@@ -29,7 +29,7 @@ def test_deepseek_completion_logic(mock_post: MagicMock) -> None:
}
mock_post.return_value = mock_response
result = ai_client.send_result(md_content="Context", user_message="Hi", base_dir=".")
result = ai_client.send(md_content="Context", user_message="Hi", base_dir=".")
assert result.ok
assert result.data == "Hello World"
assert mock_post.called
@@ -53,7 +53,7 @@ def test_deepseek_reasoning_logic(mock_post: MagicMock) -> None:
}
mock_post.return_value = mock_response
result = ai_client.send_result(md_content="Context", user_message="Hi", base_dir=".")
result = ai_client.send(md_content="Context", user_message="Hi", base_dir=".")
assert result.ok
assert "<thinking>\nChain of thought\n</thinking>" in result.data
assert "Final answer" in result.data
@@ -96,7 +96,7 @@ def test_deepseek_tool_calling(mock_post: MagicMock) -> None:
mock_post.side_effect = [mock_resp1, mock_resp2]
mock_dispatch.return_value = "Hello World"
result = ai_client.send_result(md_content="Context", user_message="Read test.txt", base_dir=".")
result = ai_client.send(md_content="Context", user_message="Read test.txt", base_dir=".")
assert result.ok
assert "File content is: Hello World" in result.data
assert mock_dispatch.called
@@ -123,7 +123,7 @@ def test_deepseek_streaming(mock_post: MagicMock) -> None:
mock_response.iter_lines.return_value = [c.encode('utf-8') for c in chunks]
mock_post.return_value = mock_response
result = ai_client.send_result(md_content="Context", user_message="Stream test", base_dir=".", stream=True)
result = ai_client.send(md_content="Context", user_message="Stream test", base_dir=".", stream=True)
assert result.ok
assert result.data == "Hello World"
@@ -144,7 +144,7 @@ def test_deepseek_payload_verification(mock_post: MagicMock) -> None:
}
mock_post.return_value = mock_response
result = ai_client.send_result(md_content="Context", user_message="Message 1", base_dir=".", discussion_history="History")
result = ai_client.send(md_content="Context", user_message="Message 1", base_dir=".", discussion_history="History")
assert result.ok
args, kwargs = mock_post.call_args
@@ -174,7 +174,7 @@ def test_deepseek_reasoner_payload_verification(mock_post: MagicMock) -> None:
}
mock_post.return_value = mock_response
result = ai_client.send_result(md_content="Context", user_message="Message 1", base_dir=".")
result = ai_client.send(md_content="Context", user_message="Message 1", base_dir=".")
assert result.ok
args, kwargs = mock_post.call_args
+1 -1
View File
@@ -36,6 +36,6 @@ def test_gemini_cli_loop_termination() -> None:
mock_process.returncode = 0
mock_popen.return_value = mock_process
ai_client.set_provider("gemini_cli", "gemini-2.0-flash")
result = ai_client.send_result("context", "prompt")
result = ai_client.send("context", "prompt")
assert result.ok
assert result.data == "Final answer"
+2 -2
View File
@@ -13,7 +13,7 @@ def test_gemini_cli_full_integration() -> None:
}
mock_adapter.last_usage = {"total_tokens": 10}
ai_client._gemini_cli_adapter = mock_adapter
result = ai_client.send_result("context", "integrated test")
result = ai_client.send("context", "integrated test")
assert result.ok
assert "Final integrated answer" in result.data
@@ -28,5 +28,5 @@ def test_gemini_cli_rejection_and_history() -> None:
}
mock_adapter.last_usage = {}
ai_client._gemini_cli_adapter = mock_adapter
result = ai_client.send_result("ctx", "msg", pre_tool_callback=lambda *a, **kw: None)
result = ai_client.send("ctx", "msg", pre_tool_callback=lambda *a, **kw: None)
assert result is not None
+1 -1
View File
@@ -10,6 +10,6 @@ def test_send_invokes_adapter_send() -> None:
mock_process.returncode = 0
mock_popen.return_value = mock_process
ai_client.set_provider("gemini_cli", "gemini-2.0-flash")
res = ai_client.send_result("context", "msg")
res = ai_client.send("context", "msg")
assert res.ok
assert res.data == "Hello from mock adapter"
+1 -1
View File
@@ -45,7 +45,7 @@ def test_mcp_tool_call_is_dispatched(app_instance: App) -> None:
mock_chat.send_message.side_effect = [mock_response_with_tool, mock_response_final]
ai_client.set_provider("gemini", "mock-model")
# 5. Call the send function
result = ai_client.send_result(
result = ai_client.send(
md_content="some context",
user_message="read the file",
base_dir=".",
+1 -1
View File
@@ -56,7 +56,7 @@ class TestHeadlessAPI(unittest.TestCase):
self.assertIn("not configured", response.json()["detail"])
def test_generate_endpoint(self) -> None:
with patch('src.ai_client.send_result', return_value=Result(data="AI Response")), \
with patch('src.ai_client.send', return_value=Result(data="AI Response")), \
patch('src.app_controller.AppController._do_generate', return_value=("md", "path", [], "stable", "disc")):
payload = {"prompt": "test prompt", "auto_add_history": False}
response = self.client.post("/api/v1/generate", json=payload, headers=self.headers)
+1 -1
View File
@@ -28,7 +28,7 @@ async def test_headless_verification_full_run(vlogger) -> None:
vlogger.log_state("T2 Status Initial", "todo", t2.status)
# We must patch where it is USED: multi_agent_conductor
with patch("src.multi_agent_conductor.ai_client.send_result") as mock_send, \
with patch("src.multi_agent_conductor.ai_client.send") as mock_send, \
patch("src.multi_agent_conductor.ai_client.reset_session") as mock_reset, \
patch("src.multi_agent_conductor.confirm_spawn", return_value=(True, "mock_prompt", "mock_ctx")):
# We need mock_send to return something that doesn't contain "BLOCKED"
+4 -4
View File
@@ -26,7 +26,7 @@ def test_user_request_integration_flow(mock_app: App) -> None:
# Mock all ai_client methods called during _handle_request_event
mock_response = "This is a test AI response"
with (
patch('src.ai_client.send_result', return_value=Result(data=mock_response)) as mock_send,
patch('src.ai_client.send', return_value=Result(data=mock_response)) as mock_send,
patch('src.ai_client.set_custom_system_prompt'),
patch('src.ai_client.set_model_params'),
patch('src.ai_client.set_agent_tools'),
@@ -52,8 +52,8 @@ def test_user_request_integration_flow(mock_app: App) -> None:
# Let's call the handler
app.controller._handle_request_event(event)
# 3. Verify ai_client.send_result was called
assert mock_send.called, "ai_client.send_result was not called"
# 3. Verify ai_client.send was called
assert mock_send.called, "ai_client.send was not called"
# 4. First event should be 'comms' (request logging)
event_name, payload = app.controller.event_queue.get()
@@ -85,7 +85,7 @@ def test_user_request_error_handling(mock_app: App) -> None:
app = mock_app
err = ErrorInfo(kind=ErrorKind.NETWORK, message="API Failure", source="ai_client.test")
with (
patch('src.ai_client.send_result', return_value=Result(data="", errors=[err])),
patch('src.ai_client.send', return_value=Result(data="", errors=[err])),
patch('src.ai_client.set_custom_system_prompt'),
patch('src.ai_client.set_model_params'),
patch('src.ai_client.set_agent_tools'),
+3 -3
View File
@@ -13,7 +13,7 @@ def test_generate_tracks() -> None:
{"id": "track_2", "title": "Refactor", "goal": "decouple modules", "type": "refactor"}
]
"""
with patch("src.ai_client.send_result", return_value=Result(data=mock_response)):
with patch("src.ai_client.send", return_value=Result(data=mock_response)):
tracks = orchestrator_pm.generate_tracks("Develop feature X", {}, [])
assert len(tracks) == 2
assert tracks[0]["id"] == "track_1"
@@ -26,7 +26,7 @@ def test_generate_tickets() -> None:
{"id": "T2", "description": "task 2", "depends_on": ["T1"]}
]
"""
with patch("src.ai_client.send_result", return_value=Result(data=mock_response)):
with patch("src.ai_client.send", return_value=Result(data=mock_response)):
tickets = conductor_tech_lead.generate_tickets("Track goal", "code skeletons")
assert len(tickets) == 2
assert tickets[0]["id"] == "T1"
@@ -105,7 +105,7 @@ def test_conductor_engine_parse_json_tickets() -> None:
def test_run_worker_lifecycle_blocked() -> None:
ticket = Ticket(id="T1", description="desc", status="todo", assigned_to="worker1")
context = WorkerContext(ticket_id="T1", model_name="model", messages=[])
with patch("src.ai_client.send_result") as mock_ai_client, \
with patch("src.ai_client.send") as mock_ai_client, \
patch("src.ai_client.reset_session"), \
patch("src.ai_client.set_provider"), \
patch("src.multi_agent_conductor.confirm_spawn", return_value=(True, "p", "c")):
+2 -2
View File
@@ -10,7 +10,7 @@ def test_worker_streaming_intermediate():
event_queue = MagicMock()
with (
patch("src.ai_client.send_result") as mock_send_result,
patch("src.ai_client.send") as mock_send,
patch("src.multi_agent_conductor._queue_put") as mock_q_put,
patch("src.multi_agent_conductor.confirm_spawn", return_value=(True, "p", "c")),
patch("src.ai_client.reset_session"),
@@ -26,7 +26,7 @@ def test_worker_streaming_intermediate():
cb({"kind": "tool_result", "payload": {"name": "test_tool", "output": "hello"}})
return Result(data="DONE")
mock_send_result.side_effect = side_effect
mock_send.side_effect = side_effect
run_worker_lifecycle(ticket, context, event_queue=event_queue)
# _queue_put(event_queue, event_name, payload)
+1 -1
View File
@@ -73,7 +73,7 @@ def test_rag_integration(mock_project):
# message sent to the provider. We use 'wraps' to let the real logic run
# while still having a mock we can inspect. We also mock the internal
# _send_gemini which is what actually "sends to the provider".
with patch('src.ai_client.send_result', wraps=ai_client.send_result) as mock_send:
with patch('src.ai_client.send', wraps=ai_client.send) as mock_send:
with patch('src.ai_client._send_gemini') as mock_provider:
mock_provider.return_value = Result(data="Mock AI Response")
+4 -4
View File
@@ -13,8 +13,8 @@ class TestRunWorkerLifecycleAbort(unittest.TestCase):
Test that run_worker_lifecycle returns early and marks ticket as 'killed'
if the abort event is set for the ticket.
"""
# Mock ai_client.send_result
with patch('src.ai_client.send_result') as mock_send_result:
# Mock ai_client.send
with patch('src.ai_client.send') as mock_send:
# Mock ticket and context
ticket = Ticket(id="T-001", description="Test task")
ticket = Ticket(id="T-001", description="Test task")
@@ -34,8 +34,8 @@ class TestRunWorkerLifecycleAbort(unittest.TestCase):
# Assert ticket status is 'killed'
self.assertEqual(ticket.status, "killed")
# Also assert ai_client.send_result was NOT called (abort fires before the call)
mock_send_result.assert_not_called()
# Also assert ai_client.send was NOT called (abort fires before the call)
mock_send.assert_not_called()
if __name__ == "__main__":
unittest.main()
+3 -3
View File
@@ -20,9 +20,9 @@ class MockDialog:
@pytest.fixture
def mock_ai_client() -> Generator[MagicMock, None, None]:
with patch("src.ai_client.send_result") as mock_send_result:
mock_send_result.return_value = Result(data="Task completed")
yield mock_send_result
with patch("src.ai_client.send") as mock_send:
mock_send.return_value = Result(data="Task completed")
yield mock_send
def test_confirm_spawn_pushed_to_queue() -> None:
event_queue = events.SyncEventQueue()
+6 -6
View File
@@ -43,7 +43,7 @@ def test_handle_request_event_appends_definitions(controller):
with (
patch('src.app_controller.parse_symbols', return_value=["Track"]) as mock_parse,
patch('src.app_controller.get_symbol_definition', return_value=("src/models.py", "class Track: pass", 42)) as mock_get_def,
patch('src.ai_client.send_result', return_value=Result(data="mocked response")) as mock_send_result
patch('src.ai_client.send', return_value=Result(data="mocked response")) as mock_send
):
# Execute
controller._handle_request_event(event)
@@ -54,8 +54,8 @@ def test_handle_request_event_appends_definitions(controller):
# Check if enriched prompt was sent to AI
expected_suffix = "\n\n[Definition: Track from src/models.py (line 42)]\n```python\nclass Track: pass\n```"
mock_send_result.assert_called_once()
args, kwargs = mock_send_result.call_args
mock_send.assert_called_once()
args, kwargs = mock_send.call_args
sent_prompt = args[1]
assert sent_prompt == "Explain @Track object" + expected_suffix
@@ -72,13 +72,13 @@ def test_handle_request_event_no_symbols(controller):
with (
patch('src.app_controller.parse_symbols', return_value=[]) as mock_parse,
patch('src.ai_client.send_result', return_value=Result(data="mocked response")) as mock_send_result
patch('src.ai_client.send', return_value=Result(data="mocked response")) as mock_send
):
# Execute
controller._handle_request_event(event)
# Verify
mock_send_result.assert_called_once()
args, kwargs = mock_send_result.call_args
mock_send.assert_called_once()
args, kwargs = mock_send.call_args
sent_prompt = args[1]
assert sent_prompt == "Just a normal prompt"
+5 -5
View File
@@ -76,17 +76,17 @@ def test_end_to_end_tier4_integration(vlogger) -> None:
vlogger.finalize("E2E Tier 4 Integration", "PASS", "ai_client.run_tier4_analysis correctly called and results merged.")
def test_ai_client_passes_qa_callback() -> None:
"""Verifies that ai_client.send_result passes the qa_callback down to the provider function."""
"""Verifies that ai_client.send passes the qa_callback down to the provider function."""
qa_callback = lambda x: "analysis"
with patch("src.ai_client._send_gemini", return_value=Result(data="ok")) as mock_send:
ai_client.set_provider("gemini", "gemini-2.5-flash-lite")
result = ai_client.send_result("ctx", "msg", qa_callback=qa_callback)
result = ai_client.send("ctx", "msg", qa_callback=qa_callback)
assert result.ok
args, kwargs = mock_send.call_args
# It might be passed as positional or keyword depending on how 'send_result' calls it
# send_result() calls _send_gemini(md_content, user_message, base_dir, ..., qa_callback, ...)
# In current impl of send_result(), it is the 7th argument after md_content, user_msg, base_dir, file_items, disc_hist, pre_tool
# It might be passed as positional or keyword depending on how 'send' calls it
# send() calls _send_gemini(md_content, user_message, base_dir, ..., qa_callback, ...)
# In current impl of send(), it is the 7th argument after md_content, user_msg, base_dir, file_items, disc_hist, pre_tool
assert args[6] == qa_callback or kwargs.get("qa_callback") == qa_callback
def test_gemini_provider_passes_qa_callback_to_run_script() -> None:
+1 -1
View File
@@ -41,7 +41,7 @@ def test_app_controller_do_generate_uses_persona_strategy(mock_build):
assert call_kwargs.get("aggregation_strategy") == "full"
@patch("src.summarize.summarise_file")
@patch("src.multi_agent_conductor.ai_client.send_result")
@patch("src.multi_agent_conductor.ai_client.send")
def test_run_worker_lifecycle_uses_strategy(mock_send, mock_summarise, tmp_path):
mock_send.return_value = Result(data="fake response")
mock_summarise.return_value = "fake summary"
+1 -1
View File
@@ -32,7 +32,7 @@ def test_token_usage_tracking() -> None:
mock_response.text = "Mock Response"
mock_chat.send_message.return_value = mock_response
ai_client.set_provider("gemini", "gemini-2.5-flash-lite")
result = ai_client.send_result("Context", "Hello")
result = ai_client.send("Context", "Hello")
assert result.ok
comms = ai_client.get_comms_log()
response_entries = [e for e in comms if e.get("direction") == "IN" and e["kind"] == "response"]