Refactor tests: break down single test into focused, modular tests
- Add pytest fixtures for shared data to avoid reparsing YAML files - Split large test into specific test functions for better modularity - Add comprehensive test coverage for busy_event, location tracking, and helper functions - Improve test performance with session-scoped fixtures - Enable individual test execution with pytest -k 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
bdc94f3ebc
commit
f89d984623
|
@ -1,68 +1,223 @@
|
|||
from datetime import date, datetime, timedelta
|
||||
from datetime import date, datetime
|
||||
|
||||
import agenda.busy
|
||||
import agenda.travel as travel
|
||||
import agenda.trip
|
||||
import pytest
|
||||
from agenda.busy import _parse_datetime_field
|
||||
from agenda.event import Event
|
||||
from web_view import app
|
||||
|
||||
|
||||
def test_get_location_for_date() -> None:
|
||||
@pytest.fixture(scope="session")
|
||||
def app_context():
|
||||
"""Set up Flask app context for tests."""
|
||||
app.config["SERVER_NAME"] = "test"
|
||||
with app.app_context():
|
||||
today = datetime.now().date()
|
||||
trips = agenda.trip.build_trip_list()
|
||||
yield
|
||||
|
||||
data_dir = app.config["PERSONAL_DATA"]
|
||||
|
||||
# Parse YAML files once for the test
|
||||
bookings = travel.parse_yaml("flights", data_dir)
|
||||
accommodations = travel.parse_yaml("accommodation", data_dir)
|
||||
airports = travel.parse_yaml("airports", data_dir)
|
||||
@pytest.fixture(scope="session")
|
||||
def trips(app_context):
|
||||
"""Load trip list once for all tests."""
|
||||
return agenda.trip.build_trip_list()
|
||||
|
||||
for year in range(2023, 2025):
|
||||
start = date(2023, 1, 1)
|
||||
busy_events = agenda.busy.get_busy_events(start, app.config, trips)
|
||||
weekends = agenda.busy.weekends(start, busy_events, trips, data_dir)
|
||||
|
||||
for weekend in weekends:
|
||||
for day in "saturday", "sunday":
|
||||
# When free (no events), should be home (None)
|
||||
# When traveling (events), should be away (City name)
|
||||
assert bool(weekend[day + "_location"][0]) == bool(weekend[day])
|
||||
@pytest.fixture(scope="session")
|
||||
def travel_data(app_context):
|
||||
"""Load travel data (bookings, accommodations, airports) once for all tests."""
|
||||
data_dir = app.config["PERSONAL_DATA"]
|
||||
return {
|
||||
"bookings": travel.parse_yaml("flights", data_dir),
|
||||
"accommodations": travel.parse_yaml("accommodation", data_dir),
|
||||
"airports": travel.parse_yaml("airports", data_dir),
|
||||
"data_dir": data_dir,
|
||||
}
|
||||
|
||||
# Test some specific cases
|
||||
april_29_location = agenda.busy.get_location_for_date(
|
||||
date(2023, 4, 29), trips, bookings, accommodations, airports
|
||||
|
||||
def test_weekend_location_consistency(app_context, trips, travel_data):
|
||||
"""Test that weekend locations are consistent with events (free=home, events=away)."""
|
||||
for year in range(2023, 2025):
|
||||
start = date(2023, 1, 1)
|
||||
busy_events = agenda.busy.get_busy_events(start, app.config, trips)
|
||||
weekends = agenda.busy.weekends(
|
||||
start, busy_events, trips, travel_data["data_dir"]
|
||||
)
|
||||
assert not april_29_location[0] # Should be home (None)
|
||||
|
||||
l = agenda.busy.get_location_for_date(
|
||||
date(2025, 2, 15), trips, bookings, accommodations, airports
|
||||
for weekend in weekends:
|
||||
for day in "saturday", "sunday":
|
||||
# When free (no events), should be home (None)
|
||||
# When traveling (events), should be away (City name)
|
||||
location_exists = bool(weekend[day + "_location"][0])
|
||||
has_events = bool(weekend[day])
|
||||
assert location_exists == has_events, (
|
||||
f"Weekend {weekend['date']} {day}: "
|
||||
f"location_exists={location_exists}, has_events={has_events}"
|
||||
)
|
||||
|
||||
|
||||
def test_specific_home_dates(travel_data):
|
||||
"""Test specific dates that should return home (None)."""
|
||||
trips = agenda.trip.build_trip_list()
|
||||
|
||||
home_dates = [
|
||||
date(2023, 4, 29),
|
||||
date(2025, 7, 1),
|
||||
date(2023, 12, 2),
|
||||
date(2023, 10, 7),
|
||||
date(2023, 2, 18),
|
||||
date(2025, 8, 2),
|
||||
]
|
||||
|
||||
for test_date in home_dates:
|
||||
location = agenda.busy.get_location_for_date(
|
||||
test_date,
|
||||
trips,
|
||||
travel_data["bookings"],
|
||||
travel_data["accommodations"],
|
||||
travel_data["airports"],
|
||||
)
|
||||
assert l[0] == "Hackettstown"
|
||||
assert not location[
|
||||
0
|
||||
], f"Expected home (None) for {test_date}, got {location[0]}"
|
||||
|
||||
l = agenda.busy.get_location_for_date(
|
||||
date(2025, 7, 1), trips, bookings, accommodations, airports
|
||||
|
||||
def test_specific_away_dates(travel_data):
|
||||
"""Test specific dates that should return away locations."""
|
||||
trips = agenda.trip.build_trip_list()
|
||||
|
||||
away_cases = [
|
||||
(date(2025, 2, 15), "Hackettstown"),
|
||||
]
|
||||
|
||||
for test_date, expected_city in away_cases:
|
||||
location = agenda.busy.get_location_for_date(
|
||||
test_date,
|
||||
trips,
|
||||
travel_data["bookings"],
|
||||
travel_data["accommodations"],
|
||||
travel_data["airports"],
|
||||
)
|
||||
assert not l[0]
|
||||
assert (
|
||||
location[0] == expected_city
|
||||
), f"Expected {expected_city} for {test_date}, got {location[0]}"
|
||||
|
||||
l = agenda.busy.get_location_for_date(
|
||||
date(2023, 12, 2), trips, bookings, accommodations, airports
|
||||
)
|
||||
assert not l[0]
|
||||
|
||||
l = agenda.busy.get_location_for_date(
|
||||
date(2023, 10, 7), trips, bookings, accommodations, airports
|
||||
)
|
||||
assert not l[0]
|
||||
def test_get_location_for_date_basic(travel_data):
|
||||
"""Test basic functionality of get_location_for_date function."""
|
||||
trips = agenda.trip.build_trip_list()
|
||||
test_date = date(2023, 1, 1)
|
||||
|
||||
l = agenda.busy.get_location_for_date(
|
||||
date(2023, 2, 18), trips, bookings, accommodations, airports
|
||||
)
|
||||
assert not l[0]
|
||||
location = agenda.busy.get_location_for_date(
|
||||
test_date,
|
||||
trips,
|
||||
travel_data["bookings"],
|
||||
travel_data["accommodations"],
|
||||
travel_data["airports"],
|
||||
)
|
||||
|
||||
l = agenda.busy.get_location_for_date(
|
||||
date(2025, 8, 2), trips, bookings, accommodations, airports
|
||||
)
|
||||
assert not l[0]
|
||||
# Should return a tuple with (city|None, country)
|
||||
assert isinstance(location, tuple)
|
||||
assert len(location) == 2
|
||||
assert location[1] is not None # Should always have a country
|
||||
|
||||
|
||||
def test_busy_event_classification():
|
||||
"""Test the busy_event function for different event types."""
|
||||
|
||||
# Busy event types
|
||||
busy_events = [
|
||||
Event(name="event", title="Test Event", date=date(2023, 1, 1)),
|
||||
Event(
|
||||
name="conference",
|
||||
title="Test Conference",
|
||||
date=date(2023, 1, 1),
|
||||
going=True,
|
||||
),
|
||||
Event(name="accommodation", title="Hotel", date=date(2023, 1, 1)),
|
||||
Event(name="transport", title="Flight", date=date(2023, 1, 1)),
|
||||
]
|
||||
|
||||
for event in busy_events:
|
||||
assert agenda.busy.busy_event(event), f"Event {event.name} should be busy"
|
||||
|
||||
# Non-busy events
|
||||
non_busy_events = [
|
||||
Event(
|
||||
name="conference",
|
||||
title="Test Conference",
|
||||
date=date(2023, 1, 1),
|
||||
going=False,
|
||||
),
|
||||
Event(name="other", title="Other Event", date=date(2023, 1, 1)),
|
||||
Event(name="event", title="LHG Run Club", date=date(2023, 1, 1)),
|
||||
Event(name="event", title="IA UK board meeting", date=date(2023, 1, 1)),
|
||||
]
|
||||
|
||||
for event in non_busy_events:
|
||||
assert not agenda.busy.busy_event(
|
||||
event
|
||||
), f"Event {event.name}/{event.title} should not be busy"
|
||||
|
||||
|
||||
def test_parse_datetime_field():
|
||||
"""Test the _parse_datetime_field helper function."""
|
||||
|
||||
# Test with datetime object
|
||||
dt = datetime(2023, 1, 1, 12, 0, 0)
|
||||
parsed_dt, parsed_date = _parse_datetime_field(dt)
|
||||
assert parsed_dt == dt
|
||||
assert parsed_date == date(2023, 1, 1)
|
||||
|
||||
# Test with ISO string
|
||||
iso_string = "2023-01-01T12:00:00Z"
|
||||
parsed_dt, parsed_date = _parse_datetime_field(iso_string)
|
||||
assert parsed_date == date(2023, 1, 1)
|
||||
assert parsed_dt.year == 2023
|
||||
assert parsed_dt.month == 1
|
||||
assert parsed_dt.day == 1
|
||||
|
||||
|
||||
def test_get_busy_events(app_context, trips):
|
||||
"""Test get_busy_events function."""
|
||||
start_date = date(2023, 1, 1)
|
||||
busy_events = agenda.busy.get_busy_events(start_date, app.config, trips)
|
||||
|
||||
# Should return a list
|
||||
assert isinstance(busy_events, list)
|
||||
|
||||
# All events should be Event objects
|
||||
for event in busy_events:
|
||||
assert hasattr(event, "name")
|
||||
assert hasattr(event, "as_date")
|
||||
|
||||
# Events should be sorted by date
|
||||
dates = [event.as_date for event in busy_events]
|
||||
assert dates == sorted(dates), "Events should be sorted by date"
|
||||
|
||||
|
||||
def test_weekends_function(app_context, trips, travel_data):
|
||||
"""Test the weekends function."""
|
||||
start_date = date(2023, 1, 1)
|
||||
busy_events = agenda.busy.get_busy_events(start_date, app.config, trips)
|
||||
weekends = agenda.busy.weekends(
|
||||
start_date, busy_events, trips, travel_data["data_dir"]
|
||||
)
|
||||
|
||||
# Should return a list of weekend info
|
||||
assert isinstance(weekends, list)
|
||||
assert len(weekends) == 52 # Should return 52 weekends
|
||||
|
||||
# Each weekend should have the required keys
|
||||
for weekend in weekends[:5]: # Check first 5 weekends
|
||||
assert "date" in weekend
|
||||
assert "saturday" in weekend
|
||||
assert "sunday" in weekend
|
||||
assert "saturday_location" in weekend
|
||||
assert "sunday_location" in weekend
|
||||
|
||||
# Locations should be tuples
|
||||
assert isinstance(weekend["saturday_location"], tuple)
|
||||
assert isinstance(weekend["sunday_location"], tuple)
|
||||
assert len(weekend["saturday_location"]) == 2
|
||||
assert len(weekend["sunday_location"]) == 2
|
||||
|
|
Loading…
Reference in a new issue