""" Unit Tests for Configuration Module. Tests Settings class and configuration loading. """ import pytest import os from unittest.mock import patch from app.config import Settings, get_settings, settings class TestSettingsDefaults: """Tests for Settings default values.""" def test_settings_instance_exists(self): """Test settings instance is created.""" assert settings is not None assert isinstance(settings, Settings) def test_default_environment(self): """Test default environment is development.""" s = Settings() assert s.ENVIRONMENT == "development" def test_default_debug_false(self): """Test default DEBUG is False.""" s = Settings() assert s.DEBUG is False def test_default_log_level(self): """Test default log level is INFO.""" s = Settings() assert s.LOG_LEVEL == "INFO" def test_default_max_turns(self): """Test default max turns is 20.""" s = Settings() assert s.MAX_TURNS == 20 def test_default_session_ttl(self): """Test default session TTL is 3600.""" s = Settings() assert s.SESSION_TTL == 3600 def test_default_scam_threshold(self): """Test default scam threshold is 0.7.""" s = Settings() assert s.SCAM_THRESHOLD == 0.7 def test_default_api_port(self): """Test default API port is 8000.""" s = Settings() assert s.API_PORT == 8000 def test_default_api_host(self): """Test default API host is 0.0.0.0.""" s = Settings() assert s.API_HOST == "0.0.0.0" def test_default_groq_model(self): """Test default Groq model.""" s = Settings() assert "llama" in s.GROQ_MODEL.lower() def test_default_max_message_length(self): """Test default max message length is 5000.""" s = Settings() assert s.MAX_MESSAGE_LENGTH == 5000 class TestSettingsEnvironmentProperties: """Tests for environment check properties.""" def test_is_production_false_by_default(self): """Test is_production is False by default.""" s = Settings() assert s.is_production is False def test_is_development_true_by_default(self): """Test is_development is True by default.""" s = Settings() assert s.is_development is True def test_is_testing_false_by_default(self): """Test is_testing is False by default.""" s = Settings() assert s.is_testing is False @patch.dict(os.environ, {"ENVIRONMENT": "production"}) def test_is_production_true_in_production(self): """Test is_production is True when ENVIRONMENT=production.""" s = Settings() assert s.is_production is True assert s.is_development is False assert s.is_testing is False @patch.dict(os.environ, {"ENVIRONMENT": "testing"}) def test_is_testing_true_in_testing(self): """Test is_testing is True when ENVIRONMENT=testing.""" s = Settings() assert s.is_testing is True assert s.is_production is False assert s.is_development is False class TestSettingsValidation: """Tests for Settings.validate method.""" def test_validate_returns_list(self): """Test validate returns a list.""" s = Settings() result = s.validate() assert isinstance(result, list) def test_validate_no_errors_in_development(self): """Test validate returns no errors in development.""" s = Settings() s.ENVIRONMENT = "development" result = s.validate() assert result == [] @patch.dict(os.environ, {"ENVIRONMENT": "production"}) def test_validate_errors_in_production_without_keys(self): """Test validate returns errors in production without required keys.""" s = Settings() s.GROQ_API_KEY = None s.POSTGRES_URL = None s.REDIS_URL = None result = s.validate() assert len(result) > 0 assert any("GROQ_API_KEY" in e for e in result) assert any("POSTGRES_URL" in e for e in result) assert any("REDIS_URL" in e for e in result) @patch.dict(os.environ, { "ENVIRONMENT": "production", "GROQ_API_KEY": "test-key", "POSTGRES_URL": "postgresql://test", "REDIS_URL": "redis://test" }) def test_validate_no_errors_in_production_with_keys(self): """Test validate returns no errors in production with all keys.""" s = Settings() result = s.validate() assert result == [] class TestSettingsFromEnvironment: """Tests for loading settings from environment variables.""" @patch.dict(os.environ, {"DEBUG": "true"}) def test_debug_from_env(self): """Test DEBUG is loaded from environment.""" s = Settings() assert s.DEBUG is True @patch.dict(os.environ, {"LOG_LEVEL": "DEBUG"}) def test_log_level_from_env(self): """Test LOG_LEVEL is loaded from environment.""" s = Settings() assert s.LOG_LEVEL == "DEBUG" @patch.dict(os.environ, {"MAX_TURNS": "30"}) def test_max_turns_from_env(self): """Test MAX_TURNS is loaded from environment.""" s = Settings() assert s.MAX_TURNS == 30 @patch.dict(os.environ, {"SCAM_THRESHOLD": "0.8"}) def test_scam_threshold_from_env(self): """Test SCAM_THRESHOLD is loaded from environment.""" s = Settings() assert s.SCAM_THRESHOLD == 0.8 @patch.dict(os.environ, {"API_PORT": "9000"}) def test_api_port_from_env(self): """Test API_PORT is loaded from environment.""" s = Settings() assert s.API_PORT == 9000 @patch.dict(os.environ, {"GROQ_API_KEY": "test-key-123"}) def test_groq_api_key_from_env(self): """Test GROQ_API_KEY is loaded from environment.""" s = Settings() assert s.GROQ_API_KEY == "test-key-123" @patch.dict(os.environ, {"RATE_LIMIT_PER_MINUTE": "50"}) def test_rate_limit_from_env(self): """Test RATE_LIMIT_PER_MINUTE is loaded from environment.""" s = Settings() assert s.RATE_LIMIT_PER_MINUTE == 50 class TestGetSettings: """Tests for get_settings function.""" def test_get_settings_returns_settings(self): """Test get_settings returns Settings instance.""" result = get_settings() assert isinstance(result, Settings) def test_get_settings_cached(self): """Test get_settings returns cached instance.""" result1 = get_settings() result2 = get_settings() assert result1 is result2 class TestSettingsAttributes: """Tests for Settings attribute types.""" def test_groq_max_tokens_is_int(self): """Test GROQ_MAX_TOKENS is an integer.""" s = Settings() assert isinstance(s.GROQ_MAX_TOKENS, int) def test_groq_temperature_is_float(self): """Test GROQ_TEMPERATURE is a float.""" s = Settings() assert isinstance(s.GROQ_TEMPERATURE, float) def test_session_ttl_is_int(self): """Test SESSION_TTL is an integer.""" s = Settings() assert isinstance(s.SESSION_TTL, int) def test_rate_limit_per_hour_is_int(self): """Test RATE_LIMIT_PER_HOUR is an integer.""" s = Settings() assert isinstance(s.RATE_LIMIT_PER_HOUR, int) def test_api_prefix(self): """Test API_PREFIX is set correctly.""" s = Settings() assert s.API_PREFIX == "/api/v1" def test_model_configuration(self): """Test model configuration settings.""" s = Settings() assert s.INDICBERT_MODEL is not None assert s.SPACY_MODEL is not None assert s.EMBEDDING_MODEL is not None