mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 00:27:01 +01:00
Partitioned at the section banners each file already used, into ten new modules named for what they cover. python_pkg/code_tutor is now entirely under the cap, from thirteen violations. The splitter copies the whole original header into each new file and lets ruff's F401 pass prune it - 59 imports removed correctly, versus a hand-written import block failing on every earlier test split today. That does not cover module-level helpers: _make_verifier sat between two banners and was left behind by its callers, so it moved to conftest.py, taking test_verifier.py's shadowing copy of _make_live_mock with it. No patch string changed. Pass count is 217 before and after. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
101 lines
3.0 KiB
Python
101 lines
3.0 KiB
Python
"""Tests for python_pkg.code_tutor._claude_backend."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from python_pkg.code_tutor._claude_backend import ClaudeBackend
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# ClaudeBackend.complete
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_claude_complete_with_text_block() -> None:
|
|
mock_block = MagicMock()
|
|
mock_block.text = "answer"
|
|
mock_message = MagicMock()
|
|
mock_message.content = [mock_block]
|
|
|
|
mock_client = MagicMock()
|
|
mock_client.messages.create.return_value = mock_message
|
|
|
|
with patch(
|
|
"python_pkg.code_tutor._claude_backend.anthropic.Anthropic",
|
|
return_value=mock_client,
|
|
):
|
|
backend = ClaudeBackend()
|
|
result = backend.complete("sys", "user")
|
|
|
|
assert result == "answer"
|
|
|
|
|
|
def test_claude_complete_no_text_attr() -> None:
|
|
mock_block = MagicMock(spec=[]) # no .text attribute
|
|
mock_message = MagicMock()
|
|
mock_message.content = [mock_block]
|
|
|
|
mock_client = MagicMock()
|
|
mock_client.messages.create.return_value = mock_message
|
|
|
|
with patch(
|
|
"python_pkg.code_tutor._claude_backend.anthropic.Anthropic",
|
|
return_value=mock_client,
|
|
):
|
|
backend = ClaudeBackend()
|
|
result = backend.complete("sys", "user")
|
|
|
|
assert result == ""
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# ClaudeBackend.stream
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_claude_stream_success() -> None:
|
|
mock_stream_ctx = MagicMock()
|
|
mock_stream_ctx.__enter__ = MagicMock(return_value=mock_stream_ctx)
|
|
mock_stream_ctx.__exit__ = MagicMock(return_value=False)
|
|
mock_stream_ctx.text_stream = iter(["hello", " world"])
|
|
|
|
mock_client = MagicMock()
|
|
mock_client.messages.stream.return_value = mock_stream_ctx
|
|
|
|
tokens: list[str] = []
|
|
with patch(
|
|
"python_pkg.code_tutor._claude_backend.anthropic.Anthropic",
|
|
return_value=mock_client,
|
|
):
|
|
backend = ClaudeBackend()
|
|
result = backend.stream("sys", "user", tokens.append)
|
|
|
|
assert result == "hello world"
|
|
assert tokens == ["hello", " world"]
|
|
|
|
|
|
def test_claude_stream_api_error_fallback() -> None:
|
|
import anthropic as anthropic_lib
|
|
|
|
mock_client = MagicMock()
|
|
mock_client.messages.stream.side_effect = anthropic_lib.APIError(
|
|
message="fail",
|
|
request=MagicMock(),
|
|
body=None,
|
|
)
|
|
mock_block = MagicMock()
|
|
mock_block.text = "fallback"
|
|
mock_message = MagicMock()
|
|
mock_message.content = [mock_block]
|
|
mock_client.messages.create.return_value = mock_message
|
|
|
|
tokens: list[str] = []
|
|
with patch(
|
|
"python_pkg.code_tutor._claude_backend.anthropic.Anthropic",
|
|
return_value=mock_client,
|
|
):
|
|
backend = ClaudeBackend()
|
|
result = backend.stream("sys", "user", tokens.append)
|
|
|
|
assert result == "fallback"
|