Files
ss-tools/backend/tests/plugins/test_git_llm_extension.py
busya f75c15dbc6 test: massive coverage expansion — 15 new test modules + assistant tool fixes + orthogonal testing
- 10 translate plugin test files (100% coverage on 12 modules)
- assistant/handler tools: 85+ tests covering dispatch, registry, resolvers, routes, llm_planner, 13 tool handlers
- clean release: artifact_catalog_loader, mappers, approval, publication tests
- API routes: translate_helpers, validation_service extensions, datasets to 100%
- notifications: providers/service tests
- services: profile_preference_service
- docs/orthogonal-test-report.md — full speckit.tests audit
- Fixes: 3 git_base async mock failures, 4 assistant handler permission-check patches
- .gitignore: coverage artifacts
2026-06-15 15:38:59 +03:00

159 lines
6.1 KiB
Python

# #region Test.GitLLMExtension [C:3] [TYPE Module] [SEMANTICS test, git, llm, commit, message, generation]
# @BRIEF Tests for git/llm_extension.py — GitLLMExtension.suggest_commit_message.
# @RELATION BINDS_TO -> [GitLLMExtensionModule]
# @TEST_CONTRACT: suggest_commit_message -> str | LLM-based commit message
# @TEST_EDGE: empty_response -> fallback message
# @TEST_EDGE: missing_choices -> fallback message
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))
import os
os.environ.setdefault("SECRET_KEY", "test-secret-key-for-testing")
os.environ.setdefault("DATABASE_URL", "sqlite:///:memory:")
os.environ.setdefault("AUTH_DATABASE_URL", "sqlite:///:memory:")
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from src.plugins.git.llm_extension import GitLLMExtension
class TestGitLLMExtension:
"""GitLLMExtension — commit message generation via LLM."""
def setup_method(self):
self.mock_client = MagicMock()
self.mock_client.default_model = "gpt-4o-mini"
self.extension = GitLLMExtension(self.mock_client)
def test_init_stores_client(self):
"""Client stored on init."""
assert self.extension.client is self.mock_client
@pytest.mark.asyncio
async def test_suggest_commit_message_success(self):
"""Successful LLM response returns stripped content."""
self.mock_client.client.chat.completions.create = AsyncMock()
mock_choice = MagicMock()
mock_choice.message.content = " feat: add new feature "
mock_response = MagicMock()
mock_response.choices = [mock_choice]
self.mock_client.client.chat.completions.create.return_value = mock_response
result = await self.extension.suggest_commit_message(
diff="+ new feature",
history=["feat: old feature"],
)
assert result == "feat: add new feature"
@pytest.mark.asyncio
async def test_suggest_commit_message_empty_choices(self):
"""Response with no choices returns fallback message."""
self.mock_client.client.chat.completions.create = AsyncMock()
mock_response = MagicMock()
mock_response.choices = []
mock_response.error = None
self.mock_client.client.chat.completions.create.return_value = mock_response
result = await self.extension.suggest_commit_message(
diff="+ new feature",
history=[],
)
assert result == "Update dashboard configurations (LLM generation failed)"
@pytest.mark.asyncio
async def test_suggest_commit_message_no_response(self):
"""None response returns fallback message."""
self.mock_client.client.chat.completions.create = AsyncMock()
self.mock_client.client.chat.completions.create.return_value = None
result = await self.extension.suggest_commit_message(
diff="+ new feature",
history=[],
)
assert result == "Update dashboard configurations (LLM generation failed)"
@pytest.mark.asyncio
async def test_suggest_commit_message_empty_history(self):
"""Empty history list is joined to empty string."""
self.mock_client.client.chat.completions.create = AsyncMock()
mock_choice = MagicMock()
mock_choice.message.content = "Initial commit"
mock_response = MagicMock()
mock_response.choices = [mock_choice]
self.mock_client.client.chat.completions.create.return_value = mock_response
result = await self.extension.suggest_commit_message(
diff="+ initial",
history=[],
)
assert result == "Initial commit"
@pytest.mark.asyncio
async def test_suggest_commit_message_with_history(self):
"""Multiple history entries joined by newline."""
self.mock_client.client.chat.completions.create = AsyncMock()
mock_choice = MagicMock()
mock_choice.message.content = "fix: bug"
mock_response = MagicMock()
mock_response.choices = [mock_choice]
self.mock_client.client.chat.completions.create.return_value = mock_response
result = await self.extension.suggest_commit_message(
diff="- bug line",
history=["feat: a", "fix: b"],
)
assert result == "fix: bug"
@pytest.mark.asyncio
async def test_suggest_commit_message_custom_prompt(self):
"""Custom prompt template is rendered and passed to LLM."""
self.mock_client.client.chat.completions.create = AsyncMock()
mock_choice = MagicMock()
mock_choice.message.content = "custom message"
mock_response = MagicMock()
mock_response.choices = [mock_choice]
self.mock_client.client.chat.completions.create.return_value = mock_response
with patch("src.plugins.git.llm_extension.render_prompt") as mock_render:
mock_render.return_value = "Custom template output"
await self.extension.suggest_commit_message(
diff="+ change",
history=["prev"],
prompt_template="Custom template with {history} and {diff}",
)
mock_render.assert_called_once()
call_args = mock_render.call_args[0]
assert "Custom template" in call_args[0]
@pytest.mark.asyncio
async def test_suggest_commit_message_model_and_temp(self):
"""Correct model and temperature passed to LLM."""
self.mock_client.client.chat.completions.create = AsyncMock()
mock_choice = MagicMock()
mock_choice.message.content = "msg"
mock_response = MagicMock()
mock_response.choices = [mock_choice]
self.mock_client.client.chat.completions.create.return_value = mock_response
await self.extension.suggest_commit_message(
diff="+ change",
history=["prev"],
)
call_kwargs = self.mock_client.client.chat.completions.create.call_args[1]
assert call_kwargs["model"] == "gpt-4o-mini"
assert call_kwargs["temperature"] == 0.7
assert len(call_kwargs["messages"]) == 1
assert call_kwargs["messages"][0]["role"] == "user"
# #endregion Test.GitLLMExtension