[OpenSpec 与项目骨架]:完成实施型变更与 Python 基础骨架,包含 OpenSpec 工件、核心模型、配置边界和基础测试
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import unittest
|
||||
|
||||
from owner_voice_pet.config import AppConfig
|
||||
from owner_voice_pet.models import (
|
||||
AudioFrame,
|
||||
AudioSegment,
|
||||
ErrorCode,
|
||||
Message,
|
||||
PipelineState,
|
||||
ProviderError,
|
||||
)
|
||||
|
||||
|
||||
class ModelsConfigTests(unittest.TestCase):
|
||||
def test_audio_frame_validates_core_fields(self) -> None:
|
||||
frame = AudioFrame(
|
||||
pcm=b"\x00\x00",
|
||||
sample_rate=16000,
|
||||
channels=1,
|
||||
timestamp_ms=10,
|
||||
frame_id=1,
|
||||
metadata={"wake": True},
|
||||
)
|
||||
self.assertEqual(frame.sample_rate, 16000)
|
||||
self.assertTrue(frame.metadata["wake"])
|
||||
|
||||
def test_audio_segment_duration(self) -> None:
|
||||
segment = AudioSegment(
|
||||
pcm=b"\x00\x00\x01\x00",
|
||||
sample_rate=16000,
|
||||
channels=1,
|
||||
start_time_ms=100,
|
||||
end_time_ms=450,
|
||||
)
|
||||
self.assertEqual(segment.duration_ms, 350)
|
||||
|
||||
def test_invalid_audio_frame_rejected(self) -> None:
|
||||
with self.assertRaises(ValueError):
|
||||
AudioFrame(b"", 0, 1, 0, 0)
|
||||
|
||||
def test_provider_error_string_is_structured(self) -> None:
|
||||
error = ProviderError(
|
||||
ErrorCode.LLM_API_KEY_MISSING,
|
||||
"missing key",
|
||||
False,
|
||||
"openai-compatible",
|
||||
"llm",
|
||||
)
|
||||
self.assertIn("LLM_API_KEY_MISSING", str(error))
|
||||
self.assertIn("llm/openai-compatible", str(error))
|
||||
|
||||
def test_config_from_env_masks_secret_boundary(self) -> None:
|
||||
old_env = dict(os.environ)
|
||||
try:
|
||||
os.environ["OWNER_LLM_BASE_URL"] = "https://newapi.mkbk.shop/"
|
||||
os.environ["OWNER_LLM_API_KEY"] = "secret-value"
|
||||
os.environ["OWNER_LLM_MODEL"] = "test-model"
|
||||
config = AppConfig.from_env()
|
||||
self.assertEqual(config.llm_base_url, "https://newapi.mkbk.shop")
|
||||
self.assertEqual(config.llm_api_key, "secret-value")
|
||||
self.assertEqual(config.llm_model, "test-model")
|
||||
self.assertEqual(config.validate_basic(), [])
|
||||
finally:
|
||||
os.environ.clear()
|
||||
os.environ.update(old_env)
|
||||
|
||||
def test_missing_llm_key_has_structured_error(self) -> None:
|
||||
config = AppConfig(llm_api_key=None)
|
||||
with self.assertRaises(ProviderError) as raised:
|
||||
config.require_llm_credentials()
|
||||
self.assertEqual(raised.exception.code, ErrorCode.LLM_API_KEY_MISSING)
|
||||
|
||||
def test_pipeline_states_include_required_names(self) -> None:
|
||||
self.assertEqual(PipelineState.WAKE_LISTENING.value, "wake_listening")
|
||||
self.assertEqual(PipelineState.ERROR_RECOVERING.value, "error_recovering")
|
||||
|
||||
def test_message_model_accepts_roles(self) -> None:
|
||||
message = Message(role="user", content="你好", created_at=1.0)
|
||||
self.assertEqual(message.role, "user")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user