From e789d8123096c3275740c16ef3b7386eef2ef3cc Mon Sep 17 00:00:00 2001 From: starmen1265 Date: Fri, 13 Mar 2026 17:15:35 +0800 Subject: [PATCH] test(01-03): add failing tests for configuration management - Test KBSettings required fields (base_path, archive_path) - Test KBSettings optional fields with defaults - Test secret fields (hf_token, zhihu_cookie) as SecretStr - Test missing required fields raises ValidationError - Test get_settings returns singleton via lru_cache - Test env vars with KB_ prefix are read Co-Authored-By: Claude Opus 4.6 --- tests/test_pipeline/test_config.py | 143 +++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 tests/test_pipeline/test_config.py diff --git a/tests/test_pipeline/test_config.py b/tests/test_pipeline/test_config.py new file mode 100644 index 0000000..8e2edd7 --- /dev/null +++ b/tests/test_pipeline/test_config.py @@ -0,0 +1,143 @@ +"""Tests for configuration management module + +Tests for KBSettings and get_settings function using pydantic-settings. +""" + +import os +import pytest +from pathlib import Path +from unittest.mock import patch, MagicMock +from pydantic import ValidationError as PydanticValidationError + +from kb_pipeline.config import KBSettings, get_settings + + +class TestKBSettings: + """Tests for KBSettings class""" + + def test_kbsettings_has_base_path_field(self): + """Test KBSettings has base_path field""" + settings = KBSettings( + base_path="/tmp/kb", + archive_path="/tmp/archive" + ) + assert settings.base_path == "/tmp/kb" + + def test_kbsettings_has_archive_path_field(self): + """Test KBSettings has archive_path field""" + settings = KBSettings( + base_path="/tmp/kb", + archive_path="/tmp/archive" + ) + assert settings.archive_path == "/tmp/archive" + + def test_kbsettings_optional_fields_have_defaults(self): + """Test optional fields have empty string defaults""" + settings = KBSettings( + base_path="/tmp/kb", + archive_path="/tmp/archive" + ) + assert settings.git_root == "" + assert settings.git_user == "" + assert settings.git_email == "" + + def test_kbsettings_hf_token_is_secret(self): + """Test hf_token is SecretStr type""" + from pydantic import SecretStr + settings = KBSettings( + base_path="/tmp/kb", + archive_path="/tmp/archive", + hf_token="secret_token" + ) + assert isinstance(settings.hf_token, SecretStr) + + def test_kbsettings_zhihu_cookie_is_secret(self): + """Test zhihu_cookie is SecretStr type""" + from pydantic import SecretStr + settings = KBSettings( + base_path="/tmp/kb", + archive_path="/tmp/archive", + zhihu_cookie="secret_cookie" + ) + assert isinstance(settings.zhihu_cookie, SecretStr) + + def test_kbsettings_missing_base_path_raises_error(self): + """Test missing base_path raises ValidationError""" + with pytest.raises(PydanticValidationError) as exc_info: + KBSettings(archive_path="/tmp/archive") + assert "base_path" in str(exc_info.value) + + def test_kbsettings_missing_archive_path_raises_error(self): + """Test missing archive_path raises ValidationError""" + with pytest.raises(PydanticValidationError) as exc_info: + KBSettings(base_path="/tmp/kb") + assert "archive_path" in str(exc_info.value) + + def test_kbsettings_can_set_optional_fields(self): + """Test optional fields can be set""" + settings = KBSettings( + base_path="/tmp/kb", + archive_path="/tmp/archive", + git_root="/tmp/repo", + git_user="testuser", + git_email="test@example.com" + ) + assert settings.git_root == "/tmp/repo" + assert settings.git_user == "testuser" + assert settings.git_email == "test@example.com" + + +class TestGetSettings: + """Tests for get_settings function""" + + def test_get_settings_returns_kbsettings(self): + """Test get_settings returns KBSettings instance""" + with patch.dict(os.environ, { + "KB_BASE_PATH": "/tmp/kb", + "KB_ARCHIVE_PATH": "/tmp/archive" + }, clear=False): + # Clear cache before test + get_settings.cache_clear() + settings = get_settings() + assert isinstance(settings, KBSettings) + + def test_get_settings_returns_singleton(self): + """Test get_settings returns same instance (cached)""" + with patch.dict(os.environ, { + "KB_BASE_PATH": "/tmp/kb", + "KB_ARCHIVE_PATH": "/tmp/archive" + }, clear=False): + # Clear cache before test + get_settings.cache_clear() + settings1 = get_settings() + settings2 = get_settings() + assert settings1 is settings2 + + def test_get_settings_uses_env_vars_with_prefix(self): + """Test get_settings reads from KB_ prefixed env vars""" + with patch.dict(os.environ, { + "KB_BASE_PATH": "/custom/kb", + "KB_ARCHIVE_PATH": "/custom/archive" + }, clear=False): + # Clear cache before test + get_settings.cache_clear() + settings = get_settings() + assert settings.base_path == "/custom/kb" + assert settings.archive_path == "/custom/archive" + + +class TestKBSettingsEnvFile: + """Tests for KBSettings env file loading""" + + def test_kbsettings_model_config_has_env_file(self): + """Test KBSettings model_config has env_file setting""" + assert hasattr(KBSettings, "model_config") + assert "env_file" in KBSettings.model_config + + def test_kbsettings_model_config_has_env_prefix(self): + """Test KBSettings model_config has env_prefix setting""" + assert KBSettings.model_config.get("env_prefix") == "KB_" + + def test_kbsettings_model_config_ignores_extra(self): + """Test KBSettings model_config ignores extra fields""" + assert KBSettings.model_config.get("extra") == "ignore"