Spaces:
Sleeping
Sleeping
File size: 5,203 Bytes
e29625a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
import pytest
import yaml
import json
from unittest.mock import patch
# Import the Settings class specifically to allow for instance management in tests
from blossomtune_gradio.settings import Settings
@pytest.fixture(autouse=True)
def reset_settings_singleton():
"""
Fixture to automatically reset the Settings singleton before each test.
This allows creating a new, clean instance for each test scenario by
directly resetting the internal `_instance` variable.
"""
Settings._instance = None
@pytest.fixture
def valid_config_files(tmp_path):
"""Creates a valid config and schema file in a temporary directory."""
config_dir = tmp_path / "config"
config_dir.mkdir()
config_content = {
"ui": {
"welcome_message_md": "Hello, {{ name }}!",
"error_message_md": "An error occurred.",
}
}
schema_content = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"ui": {
"type": "object",
"properties": {
"welcome_message_md": {"type": "string"},
"error_message_md": {"type": "string"},
},
"required": ["welcome_message_md", "error_message_md"],
}
},
"required": ["ui"],
}
config_path = config_dir / "blossomtune.yaml"
schema_path = config_dir / "blossomtune.schema.json"
with open(config_path, "w") as f:
yaml.dump(config_content, f)
with open(schema_path, "w") as f:
json.dump(schema_content, f)
return str(config_path), str(schema_path)
def test_load_valid_config(valid_config_files):
"""Tests successful loading of a valid configuration."""
config_path, schema_path = valid_config_files
settings = Settings(config_path=config_path, schema_path=schema_path)
assert "welcome_message_md" in settings.templates
assert "error_message_md" in settings.templates
rendered_text = settings.get_text("welcome_message_md", name="World")
assert rendered_text == "Hello, World!"
def test_missing_config_file(tmp_path, capsys):
"""Tests handling of a missing configuration file and captures stdout."""
schema_path = tmp_path / "schema.json"
schema_path.touch() # Create an empty schema for the test
settings = Settings(config_path="nonexistent.yaml", schema_path=str(schema_path))
assert not settings.templates
# Check that an error was printed to the console
captured = capsys.readouterr()
assert "Error: Configuration file not found" in captured.out
def test_invalid_yaml_file(tmp_path, capsys):
"""Tests handling of a syntactically incorrect YAML file."""
config_path = tmp_path / "invalid.yaml"
schema_path = tmp_path / "schema.json"
schema_path.touch()
with open(config_path, "w") as f:
f.write("ui: { welcome: 'Hello'") # Malformed YAML
settings = Settings(config_path=str(config_path), schema_path=str(schema_path))
assert not settings.templates
captured = capsys.readouterr()
assert "Error parsing YAML file" in captured.out
def test_schema_validation_failure(tmp_path, capsys):
"""Tests that validation fails if the config doesn't match the schema."""
config_dir = tmp_path / "config"
config_dir.mkdir()
# Config is missing the required 'error_message'
config_content = {"ui": {"welcome_message_md": "Hello!"}}
schema_content = {
"type": "object",
"properties": {"ui": {"type": "object", "required": ["error_message_md"]}},
}
config_path = config_dir / "blossomtune.yaml"
schema_path = config_dir / "blossomtune.schema.json"
with open(config_path, "w") as f:
yaml.dump(config_content, f)
with open(schema_path, "w") as f:
json.dump(schema_content, f)
settings = Settings(config_path=str(config_path), schema_path=str(schema_path))
assert not settings.templates
captured = capsys.readouterr()
assert "Error: YAML configuration is invalid" in captured.out
@patch("blossomtune_gradio.config.BLOSSOMTUNE_CONFIG")
def test_load_from_env_variable(mock_config_env, valid_config_files):
"""Tests loading the config path from an environment variable."""
config_path, schema_path = valid_config_files
mock_config_env = config_path
# By patching the config module, the Settings constructor will pick it up
with patch("blossomtune_gradio.settings.cfg.BLOSSOMTUNE_CONFIG", mock_config_env):
settings = Settings(schema_path=schema_path)
assert settings.config_path == config_path
rendered_text = settings.get_text("welcome_message_md", name="From Env")
assert rendered_text == "Hello, From Env!"
def test_singleton_pattern(valid_config_files):
"""Tests that the same instance of Settings is always returned."""
config_path, schema_path = valid_config_files
s1 = Settings(config_path=config_path, schema_path=schema_path)
s2 = Settings() # Should return the same instance as s1
assert s1 is s2
# Verify s2 is configured, proving it's the same instance
assert "welcome_message_md" in s2.templates
|