Initial commit before Ralph loop

This commit is contained in:
Andrew Charlwood
2026-02-04 13:04:29 +00:00
commit fdd33a67af
89 changed files with 20660 additions and 0 deletions
+373
View File
@@ -0,0 +1,373 @@
"""
Tests for core/models.py - AnalysisFilters dataclass.
Tests cover:
- Basic instantiation
- validate() method for filter validation
- Property accessors (has_trust_filter, etc.)
- title property (custom vs auto-generated)
- summary() method
"""
from datetime import date
from pathlib import Path
import pytest
from core.models import AnalysisFilters
class TestAnalysisFiltersBasic:
"""Test basic AnalysisFilters instantiation and access."""
def test_create_with_required_dates(self, sample_date_range):
"""Should be able to create AnalysisFilters with just dates."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
)
assert filters.start_date == start
assert filters.end_date == end
assert filters.last_seen_date == last_seen
def test_default_lists_are_empty(self, sample_date_range):
"""Default filter lists should be empty."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
)
assert filters.trusts == []
assert filters.drugs == []
assert filters.directories == []
def test_default_minimum_patients_is_zero(self, sample_date_range):
"""Default minimum_patients should be 0."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
)
assert filters.minimum_patients == 0
def test_default_custom_title_is_empty(self, sample_date_range):
"""Default custom_title should be empty string."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
)
assert filters.custom_title == ""
class TestAnalysisFiltersValidate:
"""Test validate() method."""
def test_validate_passes_valid_config(self, sample_date_range):
"""validate() should return empty list for valid configuration."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
)
errors = filters.validate()
assert errors == []
def test_validate_fails_when_end_before_start(self):
"""validate() should fail when end_date is before start_date."""
filters = AnalysisFilters(
start_date=date(2024, 12, 31), # Later
end_date=date(2024, 1, 1), # Earlier
last_seen_date=date(2024, 6, 1),
)
errors = filters.validate()
assert len(errors) >= 1
assert any("cannot be before start date" in e for e in errors)
def test_validate_fails_when_last_seen_after_end(self):
"""validate() should fail when last_seen_date is after end_date."""
filters = AnalysisFilters(
start_date=date(2024, 1, 1),
end_date=date(2024, 6, 1),
last_seen_date=date(2024, 12, 31), # After end_date
)
errors = filters.validate()
assert len(errors) >= 1
assert any("would exclude all patients" in e for e in errors)
def test_validate_fails_when_minimum_patients_negative(self, sample_date_range):
"""validate() should fail when minimum_patients is negative."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
minimum_patients=-1,
)
errors = filters.validate()
assert len(errors) >= 1
assert any("cannot be negative" in e for e in errors)
def test_validate_fails_when_output_dir_missing(self, sample_date_range, temp_dir: Path):
"""validate() should fail when output_dir doesn't exist."""
start, end, last_seen = sample_date_range
nonexistent_dir = temp_dir / "nonexistent"
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
output_dir=nonexistent_dir,
)
errors = filters.validate()
assert len(errors) >= 1
assert any("does not exist" in e for e in errors)
def test_validate_passes_when_output_dir_exists(self, sample_date_range, temp_dir: Path):
"""validate() should pass when output_dir exists."""
start, end, last_seen = sample_date_range
output_dir = temp_dir / "output"
output_dir.mkdir()
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
output_dir=output_dir,
)
errors = filters.validate()
assert errors == []
def test_validate_multiple_errors(self):
"""validate() should report all errors, not just the first."""
filters = AnalysisFilters(
start_date=date(2024, 12, 31), # End before start
end_date=date(2024, 1, 1),
last_seen_date=date(2024, 6, 1),
minimum_patients=-5, # Negative
)
errors = filters.validate()
assert len(errors) >= 2
class TestAnalysisFiltersHasFilters:
"""Test has_*_filter properties."""
def test_has_trust_filter_false_when_empty(self, sample_date_range):
"""has_trust_filter should be False when trusts list is empty."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
)
assert filters.has_trust_filter is False
def test_has_trust_filter_true_when_populated(self, sample_date_range, sample_trusts):
"""has_trust_filter should be True when trusts list has items."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
trusts=sample_trusts,
)
assert filters.has_trust_filter is True
def test_has_drug_filter_false_when_empty(self, sample_date_range):
"""has_drug_filter should be False when drugs list is empty."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
)
assert filters.has_drug_filter is False
def test_has_drug_filter_true_when_populated(self, sample_date_range, sample_drugs):
"""has_drug_filter should be True when drugs list has items."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
drugs=sample_drugs,
)
assert filters.has_drug_filter is True
def test_has_directory_filter_false_when_empty(self, sample_date_range):
"""has_directory_filter should be False when directories list is empty."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
)
assert filters.has_directory_filter is False
def test_has_directory_filter_true_when_populated(self, sample_date_range, sample_directories):
"""has_directory_filter should be True when directories list has items."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
directories=sample_directories,
)
assert filters.has_directory_filter is True
class TestAnalysisFiltersTitle:
"""Test title property."""
def test_title_returns_custom_when_set(self, sample_date_range):
"""title should return custom_title when set."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
custom_title="My Custom Analysis",
)
assert filters.title == "My Custom Analysis"
def test_title_auto_generates_when_not_set(self, sample_date_range):
"""title should auto-generate from dates when custom_title is empty."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
)
assert "2024-01-01" in filters.title
assert "2024-12-31" in filters.title
def test_title_auto_generated_includes_dates(self):
"""Auto-generated title should include start and end dates."""
filters = AnalysisFilters(
start_date=date(2023, 6, 15),
end_date=date(2024, 3, 20),
last_seen_date=date(2024, 1, 1),
)
assert "2023-06-15" in filters.title
assert "2024-03-20" in filters.title
class TestAnalysisFiltersSummary:
"""Test summary() method."""
def test_summary_returns_string(self, sample_date_range):
"""summary() should return a string."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
)
summary = filters.summary()
assert isinstance(summary, str)
def test_summary_includes_date_range(self, sample_date_range):
"""summary() should include date range information."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
)
summary = filters.summary()
assert "Date range" in summary
assert "2024-01-01" in summary or str(start) in summary
def test_summary_includes_minimum_patients(self, sample_date_range):
"""summary() should include minimum patients value."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
minimum_patients=10,
)
summary = filters.summary()
assert "Minimum patients" in summary
assert "10" in summary
def test_summary_shows_all_when_no_filters(self, sample_date_range):
"""summary() should show 'All' when filter lists are empty."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
)
summary = filters.summary()
assert "Trusts: All" in summary
assert "Drugs: All" in summary
assert "Directories: All" in summary
def test_summary_shows_count_when_filters_set(
self, sample_date_range, sample_trusts, sample_drugs, sample_directories
):
"""summary() should show count when filter lists are populated."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
trusts=sample_trusts,
drugs=sample_drugs,
directories=sample_directories,
)
summary = filters.summary()
assert "3 selected" in summary # trusts count
assert "4 selected" in summary # drugs count
def test_summary_includes_custom_title_when_set(self, sample_date_range):
"""summary() should include custom title when set."""
start, end, last_seen = sample_date_range
filters = AnalysisFilters(
start_date=start,
end_date=end,
last_seen_date=last_seen,
custom_title="Special Analysis",
)
summary = filters.summary()
assert "Custom title" in summary
assert "Special Analysis" in summary