Coverage for tests / unit / ai / providers / test_base.py: 97%
37 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Tests for base AI provider."""
3from __future__ import annotations
5import pytest
6from assertpy import assert_that
8from lintro.ai.providers.base import AIResponse, BaseAIProvider
11def test_ai_response_defaults():
12 """Verify that AIResponse fields default to zero or empty when not provided."""
13 resp = AIResponse(content="hello", model="test")
14 assert_that(resp.content).is_equal_to("hello")
15 assert_that(resp.model).is_equal_to("test")
16 assert_that(resp.input_tokens).is_equal_to(0)
17 assert_that(resp.output_tokens).is_equal_to(0)
18 assert_that(resp.cost_estimate).is_equal_to(0.0)
19 assert_that(resp.provider).is_equal_to("")
22def test_ai_response_with_all_fields():
23 """Verify that AIResponse stores all explicitly provided field values."""
24 resp = AIResponse(
25 content="test",
26 model="gpt-4o",
27 input_tokens=100,
28 output_tokens=50,
29 cost_estimate=0.005,
30 provider="openai",
31 )
32 assert_that(resp.input_tokens).is_equal_to(100)
33 assert_that(resp.cost_estimate).is_equal_to(0.005)
36def test_base_ai_provider_complete_subclass():
37 """A complete BaseAIProvider subclass can be instantiated."""
39 class TestProvider(BaseAIProvider):
40 def __init__(self) -> None:
41 super().__init__(
42 provider_name="test",
43 has_sdk=True,
44 sdk_package="test",
45 default_model="test-model",
46 default_api_key_env="TEST_KEY",
47 )
49 def _create_client(self, *, api_key: str) -> object:
50 return None
52 def complete(
53 self,
54 prompt: str,
55 *,
56 system: str | None = None,
57 max_tokens: int = 1024,
58 timeout: float = 60.0,
59 ) -> AIResponse:
60 return AIResponse(
61 content="ok",
62 model="test",
63 )
65 provider = TestProvider()
66 assert_that(provider.name).is_equal_to("test")
67 assert_that(provider.model_name).is_equal_to("test-model")
69 result = provider.complete("hello")
70 assert_that(result.content).is_equal_to("ok")
73def test_base_ai_provider_cannot_instantiate_directly():
74 """BaseAIProvider is abstract and cannot be instantiated."""
75 with pytest.raises(TypeError):
76 BaseAIProvider( # type: ignore[abstract]
77 provider_name="test",
78 has_sdk=True,
79 sdk_package="test",
80 default_model="m",
81 default_api_key_env="K",
82 )
85def test_incomplete_subclass_fails():
86 """A subclass missing abstract methods cannot be instantiated."""
88 class IncompleteProvider(BaseAIProvider):
89 pass
91 with pytest.raises(TypeError):
92 IncompleteProvider( # type: ignore[abstract]
93 provider_name="test",
94 has_sdk=True,
95 sdk_package="test",
96 default_model="m",
97 default_api_key_env="K",
98 )