Coverage for tests / unit / ai / providers / test_factory.py: 100%

32 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""Tests for AI provider factory.""" 

2 

3from __future__ import annotations 

4 

5from unittest.mock import patch 

6 

7import pytest 

8from assertpy import assert_that 

9 

10from lintro.ai.config import AIConfig 

11from lintro.ai.providers import anthropic as anthropic_mod 

12from lintro.ai.providers import get_provider 

13from lintro.ai.providers import openai as openai_mod 

14 

15 

16def test_get_provider_anthropic(): 

17 """Verify that get_provider returns an Anthropic provider when configured.""" 

18 config = AIConfig(provider="anthropic") # type: ignore[arg-type] # Pydantic coerces str 

19 with patch.object(anthropic_mod, "_has_anthropic", True): 

20 provider = get_provider(config) 

21 assert_that(provider.name).is_equal_to("anthropic") 

22 

23 

24def test_get_provider_openai(): 

25 """Verify that get_provider returns an OpenAI provider when configured.""" 

26 config = AIConfig(provider="openai") # type: ignore[arg-type] # Pydantic coerces str 

27 with patch.object(openai_mod, "_has_openai", True): 

28 provider = get_provider(config) 

29 assert_that(provider.name).is_equal_to("openai") 

30 

31 

32def test_get_provider_unknown_raises(): 

33 """Verify that get_provider raises ValueError for an unknown provider name.""" 

34 # Bypass Pydantic validation to test the factory's own guard. 

35 config = AIConfig.model_construct(provider="unknown") 

36 with pytest.raises(ValueError, match="Unknown AI provider"): 

37 get_provider(config) 

38 

39 

40def test_get_provider_case_insensitive(): 

41 """Verify that get_provider handles provider names case-insensitively.""" 

42 # Bypass Pydantic Literal validation to test the factory lowercases. 

43 config = AIConfig.model_construct( 

44 provider="Anthropic", 

45 model=None, 

46 api_key_env=None, 

47 max_tokens=4096, 

48 ) 

49 with patch.object(anthropic_mod, "_has_anthropic", True): 

50 provider = get_provider(config) 

51 assert_that(provider.name).is_equal_to("anthropic") 

52 

53 

54def test_get_provider_passes_model(): 

55 """Verify that get_provider forwards the configured model to the provider.""" 

56 config = AIConfig( 

57 provider="anthropic", # type: ignore[arg-type] # Pydantic coerces str 

58 model="claude-opus-4-20250514", 

59 ) 

60 with patch.object(anthropic_mod, "_has_anthropic", True): 

61 provider = get_provider(config) 

62 assert_that(provider.model_name).is_equal_to( 

63 "claude-opus-4-20250514", 

64 )