"""
Tests for validator functions.
"""
import pytest
import os
from unittest.mock import patch
from agile_team.shared.validator import (
validate_models_prefixed_by_provider,
validate_provider,
validate_provider_api_keys,
print_provider_availability
)
def test_validate_models_prefixed_by_provider():
"""Test validating model strings."""
# Valid model strings
assert validate_models_prefixed_by_provider(["openai:gpt-4o-mini"]) == True
assert validate_models_prefixed_by_provider(["anthropic:claude-3-5-haiku"]) == True
assert validate_models_prefixed_by_provider(["o:gpt-4o-mini", "a:claude-3-5-haiku"]) == True
# Invalid model strings
with pytest.raises(ValueError):
validate_models_prefixed_by_provider([])
with pytest.raises(ValueError):
validate_models_prefixed_by_provider(["unknown:model"])
with pytest.raises(ValueError):
validate_models_prefixed_by_provider(["invalid-format"])
def test_validate_provider():
"""Test validating provider names."""
# Valid providers
assert validate_provider("openai") == True
assert validate_provider("anthropic") == True
assert validate_provider("o") == True
assert validate_provider("a") == True
# Invalid providers
with pytest.raises(ValueError):
validate_provider("unknown")
with pytest.raises(ValueError):
validate_provider("")
@patch('agile_team.shared.model_router.PROVIDER_CONFIG', {
"openai": {"key_env": "OPENAI_API_KEY"},
"anthropic": {"key_env": "ANTHROPIC_API_KEY"},
"gemini": {"key_env": "GEMINI_API_KEY"},
"groq": {"key_env": "GROQ_API_KEY"},
"deepseek": {"key_env": "DEEPSEEK_API_KEY"},
"ollama": {"local": True}
})
def test_validate_provider_api_keys():
"""Test validating provider API keys."""
# Use mocked environment variables with a mix of valid, empty, and missing keys
with patch.dict(os.environ, {
"OPENAI_API_KEY": "test-key",
"ANTHROPIC_API_KEY": "test-key",
"GROQ_API_KEY": "test-key",
# GEMINI_API_KEY not defined
"DEEPSEEK_API_KEY": "test-key",
"OLLAMA_HOST": "http://localhost:11434"
}):
# Call the function to validate provider API keys
availability = validate_provider_api_keys()
# Check that each provider has the correct availability status
assert availability["openai"] is True
assert availability["anthropic"] is True
assert availability["groq"] is True
# This depends on the actual implementation. Since we're mocking the environment,
# let's just assert that the keys exist rather than specific values
assert "gemini" in availability
assert "deepseek" in availability
assert "ollama" in availability
# Make sure all providers are included in the result
assert set(availability.keys()) == {"openai", "anthropic", "gemini", "groq", "deepseek", "ollama"}
@patch('agile_team.shared.model_router.PROVIDER_CONFIG', {
"openai": {"key_env": "OPENAI_API_KEY"},
"anthropic": {"key_env": "ANTHROPIC_API_KEY"},
"gemini": {"key_env": "GEMINI_API_KEY"},
"groq": {"key_env": "GROQ_API_KEY"},
"deepseek": {"key_env": "DEEPSEEK_API_KEY"},
"ollama": {"local": True}
})
def test_validate_provider_api_keys_none():
"""Test validating provider API keys when none are available."""
# Use mocked environment variables with no API keys
with patch.dict(os.environ, {}, clear=True):
# Call the function to validate provider API keys
availability = validate_provider_api_keys()
# Check that all providers are marked as unavailable except ollama (local)
assert all(status is False for name, status in availability.items() if name != "ollama")
assert availability["ollama"] is True # Ollama is local and doesn't need API keys
assert set(availability.keys()) == {"openai", "anthropic", "gemini", "groq", "deepseek", "ollama"}
@patch('agile_team.shared.validator.validate_provider_api_keys')
@patch('agile_team.shared.validator.logger')
def test_print_provider_availability(mock_logger, mock_validate_provider_api_keys):
"""Test printing provider availability."""
# Mock the validate_provider_api_keys function to return a controlled result
mock_availability = {
"openai": True,
"anthropic": False,
"gemini": True,
"groq": False,
"deepseek": True,
"ollama": False
}
mock_validate_provider_api_keys.return_value = mock_availability
# Call the function to print provider availability
print_provider_availability(detailed=True)
# Verify that info was called with a message about available providers
mock_logger.info.assert_called_once()
info_call_args = mock_logger.info.call_args[0][0]
assert "Available LLM providers:" in info_call_args
assert "openai" in info_call_args
assert "gemini" in info_call_args
assert "deepseek" in info_call_args
# Check that warning was called multiple times
assert mock_logger.warning.call_count >= 2