Files
HighCostDrugsDemo/tests/test_config.py
T
2026-02-04 13:04:29 +00:00

227 lines
8.0 KiB
Python

"""
Tests for core/config.py - PathConfig dataclass.
Tests cover:
- Default path construction
- Custom path configuration
- Path property access
- validate() method for file existence checks
- validate_fonts() method for font file checks
- as_legacy_paths() method for backwards compatibility
"""
from pathlib import Path
import pytest
from core.config import PathConfig
class TestPathConfigDefaults:
"""Test default behavior of PathConfig."""
def test_default_base_dir_is_cwd(self):
"""Default base_dir should be current working directory."""
config = PathConfig()
assert config.base_dir == Path.cwd()
def test_default_data_dir_is_under_base(self):
"""Default data_dir should be 'data' under base_dir."""
config = PathConfig()
assert config.data_dir == config.base_dir / "data"
def test_default_images_dir_is_under_base(self):
"""Default images_dir should be 'images' under base_dir."""
config = PathConfig()
assert config.images_dir == config.base_dir / "images"
class TestPathConfigCustomPaths:
"""Test custom path configuration."""
def test_custom_base_dir(self, temp_dir: Path):
"""PathConfig should accept custom base_dir."""
config = PathConfig(base_dir=temp_dir)
assert config.base_dir == temp_dir
assert config.data_dir == temp_dir / "data"
assert config.images_dir == temp_dir / "images"
class TestPathConfigProperties:
"""Test path property accessors."""
def test_drugnames_csv_path(self):
"""drugnames_csv should point to correct file."""
config = PathConfig()
assert config.drugnames_csv == config.data_dir / "drugnames.csv"
def test_directory_list_csv_path(self):
"""directory_list_csv should point to correct file."""
config = PathConfig()
assert config.directory_list_csv == config.data_dir / "directory_list.csv"
def test_treatment_function_codes_csv_path(self):
"""treatment_function_codes_csv should point to correct file."""
config = PathConfig()
assert config.treatment_function_codes_csv == config.data_dir / "treatment_function_codes.csv"
def test_drug_directory_list_csv_path(self):
"""drug_directory_list_csv should point to correct file."""
config = PathConfig()
assert config.drug_directory_list_csv == config.data_dir / "drug_directory_list.csv"
def test_org_codes_csv_path(self):
"""org_codes_csv should point to correct file."""
config = PathConfig()
assert config.org_codes_csv == config.data_dir / "org_codes.csv"
def test_include_csv_path(self):
"""include_csv should point to correct file."""
config = PathConfig()
assert config.include_csv == config.data_dir / "include.csv"
def test_default_trusts_csv_path(self):
"""default_trusts_csv should point to correct file."""
config = PathConfig()
assert config.default_trusts_csv == config.data_dir / "defaultTrusts.csv"
def test_font_medium_path(self):
"""font_medium should point to correct file."""
config = PathConfig()
assert config.font_medium == config.images_dir / "AvenirLTStd-Medium.ttf"
def test_font_roman_path(self):
"""font_roman should point to correct file."""
config = PathConfig()
assert config.font_roman == config.images_dir / "AvenirLTStd-Roman.ttf"
class TestPathConfigValidate:
"""Test validate() method."""
def test_validate_passes_when_all_files_exist(self, mock_project_dir: Path):
"""validate() should return empty list when all files exist."""
config = PathConfig(base_dir=mock_project_dir)
errors = config.validate()
assert errors == []
def test_validate_fails_when_data_dir_missing(self, temp_dir: Path):
"""validate() should report missing data directory."""
# Create images dir but not data dir
(temp_dir / "images").mkdir()
config = PathConfig(base_dir=temp_dir)
errors = config.validate()
assert len(errors) >= 1
assert any("Data directory not found" in e for e in errors)
def test_validate_fails_when_images_dir_missing(self, temp_dir: Path):
"""validate() should report missing images directory."""
# Create data dir but not images dir
(temp_dir / "data").mkdir()
config = PathConfig(base_dir=temp_dir)
errors = config.validate()
assert len(errors) >= 1
assert any("Images directory not found" in e for e in errors)
def test_validate_fails_when_required_file_missing(self, temp_dir: Path):
"""validate() should report missing required files."""
# Create directories but only some files
data_dir = temp_dir / "data"
data_dir.mkdir()
(temp_dir / "images").mkdir()
# Create only one file
(data_dir / "drugnames.csv").touch()
config = PathConfig(base_dir=temp_dir)
errors = config.validate()
# Should report 6 missing files (7 total - 1 created)
# Exclude directory-related messages (data/images directory checks)
# but include files that have "directory" in the filename
missing_file_errors = [
e for e in errors
if "not found" in e
and "Data directory not found" not in e
and "Images directory not found" not in e
]
assert len(missing_file_errors) == 6
class TestPathConfigValidateFonts:
"""Test validate_fonts() method."""
def test_validate_fonts_passes_when_fonts_exist(self, mock_project_dir: Path):
"""validate_fonts() should return empty list when fonts exist."""
config = PathConfig(base_dir=mock_project_dir)
errors = config.validate_fonts()
assert errors == []
def test_validate_fonts_fails_when_medium_font_missing(self, temp_dir: Path):
"""validate_fonts() should report missing medium font."""
images_dir = temp_dir / "images"
images_dir.mkdir()
# Create only roman font
(images_dir / "AvenirLTStd-Roman.ttf").touch()
config = PathConfig(base_dir=temp_dir)
errors = config.validate_fonts()
assert len(errors) == 1
assert "Medium font not found" in errors[0]
def test_validate_fonts_fails_when_roman_font_missing(self, temp_dir: Path):
"""validate_fonts() should report missing roman font."""
images_dir = temp_dir / "images"
images_dir.mkdir()
# Create only medium font
(images_dir / "AvenirLTStd-Medium.ttf").touch()
config = PathConfig(base_dir=temp_dir)
errors = config.validate_fonts()
assert len(errors) == 1
assert "Roman font not found" in errors[0]
class TestPathConfigLegacyPaths:
"""Test as_legacy_paths() method for backwards compatibility."""
def test_legacy_paths_returns_dict(self, temp_dir: Path):
"""as_legacy_paths() should return a dictionary."""
config = PathConfig(base_dir=temp_dir)
legacy = config.as_legacy_paths()
assert isinstance(legacy, dict)
def test_legacy_paths_contains_expected_keys(self, temp_dir: Path):
"""as_legacy_paths() should contain all expected keys."""
config = PathConfig(base_dir=temp_dir)
legacy = config.as_legacy_paths()
expected_keys = [
"drugnames_csv",
"directory_list_csv",
"treatment_function_codes_csv",
"drug_directory_list_csv",
"org_codes_csv",
"include_csv",
"default_trusts_csv",
"na_directory_rows_csv",
"ta_recommendations_xlsx",
]
for key in expected_keys:
assert key in legacy
def test_legacy_paths_have_dot_slash_prefix(self, temp_dir: Path):
"""as_legacy_paths() values should start with './'."""
config = PathConfig(base_dir=temp_dir)
legacy = config.as_legacy_paths()
for key, value in legacy.items():
assert value.startswith("./"), f"{key} should start with ./ but got {value}"