test: tighten phase 1 coverage contracts

This commit is contained in:
huanghuoguoguo
2026-05-16 10:30:17 +08:00
parent 3ba727f0e4
commit bb55cd7ba9
44 changed files with 708 additions and 1164 deletions
@@ -11,6 +11,8 @@ from unittest.mock import AsyncMock, MagicMock
import pytest
import openai # Import real openai package
from langbot.pkg.provider.modelmgr.errors import RequesterError
class TestInvokeLLMErrorHandling:
"""Tests for invoke_llm error handling branches."""
@@ -66,7 +68,7 @@ class TestInvokeLLMErrorHandling:
side_effect=asyncio.TimeoutError()
)
with pytest.raises(Exception) as exc:
with pytest.raises(RequesterError) as exc:
await requester_with_mocked_client.invoke_llm(
query=None,
model=mock_model,
@@ -87,7 +89,7 @@ class TestInvokeLLMErrorHandling:
side_effect=error
)
with pytest.raises(Exception) as exc:
with pytest.raises(RequesterError) as exc:
await requester_with_mocked_client.invoke_llm(
query=None,
model=mock_model,
@@ -108,7 +110,7 @@ class TestInvokeLLMErrorHandling:
side_effect=error
)
with pytest.raises(Exception) as exc:
with pytest.raises(RequesterError) as exc:
await requester_with_mocked_client.invoke_llm(
query=None,
model=mock_model,
@@ -129,7 +131,7 @@ class TestInvokeLLMErrorHandling:
side_effect=error
)
with pytest.raises(Exception) as exc:
with pytest.raises(RequesterError) as exc:
await requester_with_mocked_client.invoke_llm(
query=None,
model=mock_model,
@@ -175,7 +177,7 @@ class TestInvokeEmbeddingErrorHandling:
side_effect=asyncio.TimeoutError()
)
with pytest.raises(Exception) as exc:
with pytest.raises(RequesterError) as exc:
await requester_with_mocked_client.invoke_embedding(
model=mock_embedding_model,
input_text=['test'],
@@ -195,7 +197,7 @@ class TestInvokeEmbeddingErrorHandling:
side_effect=error
)
with pytest.raises(Exception) as exc:
with pytest.raises(RequesterError) as exc:
await requester_with_mocked_client.invoke_embedding(
model=mock_embedding_model,
input_text=['test'],
@@ -242,4 +244,4 @@ class TestDefaultConfig:
})
assert req.requester_cfg['base_url'] == 'https://custom.com/v1'
assert req.requester_cfg['timeout'] == 60
assert req.requester_cfg['timeout'] == 60
@@ -141,25 +141,21 @@ class TestNormalizeModalities:
requester = self._create_requester_with_mocks()
result = requester._normalize_modalities('text,image')
assert 'text' in result
assert 'image' in result
assert result == ['text', 'image']
def test_normalize_list_modalities(self):
"""Normalize list of modalities."""
requester = self._create_requester_with_mocks()
result = requester._normalize_modalities(['text', 'image', 'audio'])
assert 'text' in result
assert 'image' in result
assert 'audio' in result
assert result == ['text', 'image', 'audio']
def test_normalize_dict_modalities(self):
"""Normalize dict with nested modalities."""
requester = self._create_requester_with_mocks()
result = requester._normalize_modalities({'input': ['text'], 'output': ['text', 'image']})
assert 'text' in result
assert 'image' in result
assert result == ['text', 'image']
def test_normalize_none(self):
"""Handle None input."""
@@ -173,8 +169,7 @@ class TestNormalizeModalities:
requester = self._create_requester_with_mocks()
result = requester._normalize_modalities('text->image')
assert 'text' in result
assert 'image' in result
assert result == ['text', 'image']
class TestParseRerankResponse:
@@ -192,9 +187,10 @@ class TestParseRerankResponse:
}
result = OpenAIChatCompletions._parse_rerank_response(data)
assert len(result) == 2
assert result[0]['index'] == 0
assert result[0]['relevance_score'] == 0.95
assert result == [
{'index': 0, 'relevance_score': 0.95},
{'index': 1, 'relevance_score': 0.80},
]
def test_parse_voyage_format(self):
"""Parse Voyage AI format."""
@@ -208,8 +204,10 @@ class TestParseRerankResponse:
}
result = OpenAIChatCompletions._parse_rerank_response(data)
assert len(result) == 2
assert result[0]['index'] == 0
assert result == [
{'index': 0, 'relevance_score': 0.90},
{'index': 2, 'relevance_score': 0.75},
]
def test_parse_dashscope_format(self):
"""Parse DashScope format."""
@@ -224,8 +222,7 @@ class TestParseRerankResponse:
}
result = OpenAIChatCompletions._parse_rerank_response(data)
assert len(result) == 1
assert result[0]['index'] == 0
assert result == [{'index': 0, 'relevance_score': 0.85}]
def test_parse_unknown_format(self):
"""Handle unknown format returns empty list."""
@@ -340,4 +337,4 @@ class TestExtractScanMetadata:
result = requester._extract_scan_metadata(item, 'gpt-4')
assert result['display_name'] is None
assert result['display_name'] is None
@@ -9,6 +9,8 @@ import asyncio
from unittest.mock import AsyncMock, MagicMock
import pytest
from langbot.pkg.provider.modelmgr.errors import RequesterError
class TestOllamaRequesterConfig:
"""Tests for default config."""
@@ -228,7 +230,7 @@ class TestOllamaErrorHandling:
"""TimeoutError is converted to RequesterError."""
requester_with_mocked_client.client.chat = AsyncMock(side_effect=asyncio.TimeoutError())
with pytest.raises(Exception) as exc:
with pytest.raises(RequesterError) as exc:
await requester_with_mocked_client.invoke_llm(
query=None,
model=mock_model,
@@ -259,4 +261,4 @@ class TestOllamaScanModels:
"""REQUESTER_NAME constant exists."""
from langbot.pkg.provider.modelmgr.requesters.ollamachat import REQUESTER_NAME
assert REQUESTER_NAME == 'ollama-chat'
assert REQUESTER_NAME == 'ollama-chat'
@@ -13,7 +13,6 @@ from unittest.mock import Mock
from importlib import import_module
import langbot_plugin.api.entities.builtin.provider.session as provider_session
import langbot_plugin.api.entities.builtin.provider.message as provider_message
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query