Files
TextNLPClassifierApp/tests/runtime/contract/test_runtime_config_contract.py
T

97 lines
3.8 KiB
Python

"""Contract tests for runtime-config.schema.json."""
from __future__ import annotations
import json
from pathlib import Path
import jsonschema
import pytest
from src.runtime.core.config import create_schema_registry, load_runtime_config, load_schema
def test_runtime_config_schema_validation_valid():
schema = load_schema("runtime-config.schema.json")
registry = create_schema_registry()
validator = jsonschema.Draft202012Validator(schema, registry=registry)
valid_config = {
"config_version": "1.0.0",
"paths": {"output_dir": "out/articles", "sqlite_db": "out/runtime.db"},
"roles": {
"runtime_primary": {
"role_config_version": "1.0.0",
"provider": "groq",
"model": "llama-3.1-8b-instant",
"endpoint_url": "https://api.groq.com/openai/v1",
"timeout_seconds": 30,
"max_retries": 3,
"parameters": {"temperature": 0.0},
"hygiene_prompt_version": "1.0.0",
"hygiene_schema_version": "1.0.0",
"enrichment_prompt_version": "1.0.0",
"enrichment_schema_version": "1.0.0",
},
"runtime_fallback": {
"role_config_version": "1.0.0",
"provider": "deepseek",
"model": "deepseek-chat",
"endpoint_url": "https://api.deepseek.com/v1",
"timeout_seconds": 30,
"max_retries": 3,
"parameters": {"temperature": 0.0},
"hygiene_prompt_version": "1.0.0",
"hygiene_schema_version": "1.0.0",
"enrichment_prompt_version": "1.0.0",
"enrichment_schema_version": "1.0.0",
},
},
"prompts": {
"article_content_hygiene": {
"path": "prompts/article_content_hygiene.v1.txt",
"version": "1.0.0",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
},
"article_sentiment_tags": {
"path": "prompts/article_sentiment_tags.v1.txt",
"version": "1.0.0",
"hash": "0000000000000000000000000000000000000000000000000000000000000000",
},
},
"ecp": {
"canonical_schema_reference": "specs/006-article-consolidation-runtime/contracts/ecp-snapshot.schema.json",
"classifier_module": "src.classifier.InherenceClassifier",
},
"limits": {"max_input_bytes": 1048576, "context_strategy": "fail_before_provider"},
"pricing": {
"primary_input_1k": 0.00005,
"primary_output_1k": 0.00008,
"fallback_input_1k": 0.00014,
"fallback_output_1k": 0.00028,
},
"langfuse": {"environment": "local", "trace_content_policy": "metadata_only"},
"sqlite": {"busy_timeout_ms": 5000},
}
errors = list(validator.iter_errors(valid_config))
assert len(errors) == 0, f"Schema validation errors: {[e.message for e in errors]}"
def test_runtime_config_fixture_loads_successfully():
config = load_runtime_config("runtime_config.local.json")
assert config.config_version == "1.0.0"
assert "runtime_primary" in config.roles
assert "runtime_fallback" in config.roles
assert config.roles["runtime_primary"].model == "llama-3.1-8b-instant"
def test_runtime_config_rejects_powerful_models(tmp_path: Path):
valid_base = json.loads(Path("runtime_config.local.json").read_text(encoding="utf-8"))
valid_base["roles"]["runtime_primary"]["model"] = "gpt-4o" # Forbidden powerful model
cfg_file = tmp_path / "invalid_cfg.json"
cfg_file.write_text(json.dumps(valid_base), encoding="utf-8")
with pytest.raises(ValueError, match="Forbidden powerful model"):
load_runtime_config(cfg_file)