Files
bearingsinfo/tests/test_schema_validation.py
Claude 2a35f080b5 Fix pre-existing CI failures: wrong paths, broken config validation, and bad test imports
- articles_ci.yml: fix script path (scripts/ → tools/scripts/)
- deduplicate_nomenclature.py, validate_articles_structure.py: fix parents[1] → parents[2]
  so REPO_ROOT resolves to the repo root instead of tools/
- validate/run_validations.py: fix schema_dir to use actual repo root (parents[3]) / data/schemas/
- src/config.py: fix _validate_app_config — all section keys were passed with a dotted
  prefix (e.g. "paths.inbox") as dict lookup keys, causing validation to always fail;
  strip prefix so only the leaf key is used for lookup
- tests/conftest.py: add tools/ to sys.path so scripts.* imports work; fix schemas_dir
  fixture to point to data/schemas/
- tests/test_schemas.py: use absolute path to data/schemas/ instead of relative "schemas"
- tests/test_schema_validation.py: fix schemas_dir to data/schemas/ and update expected
  schema path mappings
- tests/test_processor.py: add missing dimension_patterns, text_normalization to parsing_rules
  fixture; add logging.max_size_mb and logging.backup_count to app.yaml fixture
- tests/test_knowledge_base_builder.py: fix sys.path to point to tools/scripts/ not scripts/
- tests/test_table_scraper.py: fix sources path to src/sources/ not sources/
- CLAUDE.md: clarify schemas location, unique key distinction, coverage scope

https://claude.ai/code/session_017v9w8FTSjT5646A2W98DPV
2026-05-18 15:21:20 +00:00

186 lines
8.1 KiB
Python

#!/usr/bin/env python3
"""
Unit tests for schema validation functionality.
Tests validate that:
1. All schema files are valid JSON/YAML
2. Required fields are present in schemas
3. Schema structure is correct
4. All CSV files have corresponding schemas
"""
import json
import unittest
from pathlib import Path
class TestSchemas(unittest.TestCase):
"""Test schema file structure and validity."""
def setUp(self):
"""Set up test fixtures."""
self.repo_root = Path(__file__).parent.parent
self.schemas_dir = self.repo_root / "data" / "schemas"
self.data_dir = self.repo_root / "data"
def test_schemas_directory_exists(self):
"""Test that schemas directory exists."""
self.assertTrue(self.schemas_dir.exists(), "schemas/ directory should exist")
self.assertTrue(self.schemas_dir.is_dir(), "schemas/ should be a directory")
def test_all_schema_files_valid_json(self):
"""Test that all .yaml schema files contain valid JSON format."""
schema_files = list(self.schemas_dir.glob("*.yaml"))
self.assertGreater(len(schema_files), 0, "Should have at least one schema file")
for schema_file in schema_files:
with self.subTest(schema=schema_file.name):
with open(schema_file, encoding="utf-8") as f:
try:
# Note: These .yaml files actually contain JSON format
data = json.load(f)
self.assertIsInstance(data, dict, f"{schema_file.name} should contain a JSON object")
except json.JSONDecodeError as e:
self.fail(f"{schema_file.name} contains invalid JSON: {e}")
def test_schema_structure(self):
"""Test that each schema has required structure."""
schema_files = list(self.schemas_dir.glob("*.yaml"))
for schema_file in schema_files:
with self.subTest(schema=schema_file.name):
with open(schema_file, encoding="utf-8") as f:
schema = json.load(f)
# Check for 'tables' key
self.assertIn("tables", schema, f"{schema_file.name} should have 'tables' key")
self.assertIsInstance(schema["tables"], list, "'tables' should be a list")
# Check each table definition
for table in schema["tables"]:
with self.subTest(table=table.get("name", "unknown")):
# Required fields
self.assertIn("name", table, "Table should have 'name' field")
self.assertIn("path", table, "Table should have 'path' field")
self.assertIn("columns", table, "Table should have 'columns' field")
# Optional but recommended fields
if "uniqueKey" in table:
self.assertIsInstance(table["uniqueKey"], list, "uniqueKey should be a list")
if "sort_by" in table:
self.assertIsInstance(table["sort_by"], list, "sort_by should be a list")
def test_column_definitions(self):
"""Test that column definitions have proper structure."""
schema_files = list(self.schemas_dir.glob("*.yaml"))
for schema_file in schema_files:
with open(schema_file, encoding="utf-8") as f:
schema = json.load(f)
for table in schema["tables"]:
columns = table.get("columns", {})
for col_name, col_def in columns.items():
with self.subTest(schema=schema_file.name, table=table["name"], column=col_name):
# Column can be simple string or dict
if isinstance(col_def, dict):
# New format with required, type, description
self.assertIn("type", col_def, f"Column {col_name} should have 'type'")
valid_types = ["string", "number", "integer", "boolean"]
self.assertIn(col_def["type"], valid_types, f"Column type should be one of {valid_types}")
else:
# Old format, just a type string
valid_types = ["string", "number", "integer", "boolean"]
self.assertIn(col_def, valid_types, f"Column type should be one of {valid_types}")
def test_csv_files_have_schemas(self):
"""Test that major CSV files have corresponding schema definitions."""
# Expected CSV files and their schemas
expected_mappings = {
"data/gost/bearings.csv": "data/schemas/gost.yaml",
"data/gost/dimensions.csv": "data/schemas/gost.yaml",
"data/iso/bearings.csv": "data/schemas/iso.yaml",
"data/iso/suffixes.csv": "data/schemas/iso.yaml",
"data/brands/brands.csv": "data/schemas/brands.yaml",
"data/analogs/gost_iso.csv": "data/schemas/analogs.yaml",
}
for csv_path, schema_path in expected_mappings.items():
with self.subTest(csv=csv_path):
csv_file = self.repo_root / csv_path
schema_file = self.repo_root / schema_path
if csv_file.exists():
self.assertTrue(schema_file.exists(), f"CSV file {csv_path} should have schema {schema_path}")
# Verify the schema references this CSV
with open(schema_file, encoding="utf-8") as f:
schema = json.load(f)
paths = [table.get("path") for table in schema.get("tables", [])]
self.assertIn(csv_path, paths, f"Schema {schema_path} should reference {csv_path}")
def test_unique_keys_reference_valid_columns(self):
"""Test that uniqueKey fields reference actual columns."""
schema_files = list(self.schemas_dir.glob("*.yaml"))
for schema_file in schema_files:
with open(schema_file, encoding="utf-8") as f:
schema = json.load(f)
for table in schema["tables"]:
if "uniqueKey" in table:
columns = table.get("columns", {})
unique_keys = table["uniqueKey"]
for key in unique_keys:
with self.subTest(schema=schema_file.name, table=table["name"], key=key):
self.assertIn(key, columns, f"uniqueKey field '{key}' should be in columns")
def test_sort_by_reference_valid_columns(self):
"""Test that sort_by fields reference actual columns."""
schema_files = list(self.schemas_dir.glob("*.yaml"))
for schema_file in schema_files:
with open(schema_file, encoding="utf-8") as f:
schema = json.load(f)
for table in schema["tables"]:
if "sort_by" in table:
columns = table.get("columns", {})
sort_fields = table["sort_by"]
for field in sort_fields:
with self.subTest(schema=schema_file.name, table=table["name"], field=field):
self.assertIn(field, columns, f"sort_by field '{field}' should be in columns")
class TestSchemaRequiredFields(unittest.TestCase):
"""Test that schemas define required fields appropriately."""
def setUp(self):
"""Set up test fixtures."""
self.repo_root = Path(__file__).parent.parent
self.schemas_dir = self.repo_root / "data" / "schemas"
def test_schemas_have_descriptions(self):
"""Test that table definitions have descriptions."""
schema_files = list(self.schemas_dir.glob("*.yaml"))
for schema_file in schema_files:
with open(schema_file, encoding="utf-8") as f:
schema = json.load(f)
for table in schema["tables"]:
with self.subTest(schema=schema_file.name, table=table["name"]):
# Recommended but not strictly required
if "description" not in table:
# Just a warning, not a failure
pass
if __name__ == "__main__":
unittest.main()