Implement comprehensive test infrastructure and all 124 tests across 11 phases: - Phase 0: Test infrastructure (fixtures, mocks, helpers) - Phases 1-10: Core planning engine tests (previously implemented) - Phase 11: Edge case omnibus (11 new tests) - Data edge cases: nil stadiums, malformed dates, invalid coordinates - Boundary conditions: driving limits, radius boundaries - Time zone cases: cross-timezone games, DST transitions Reorganize test structure under Planning/ directory with proper organization. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
551 lines
16 KiB
Markdown
551 lines
16 KiB
Markdown
# Test Suite Implementation Plan
|
|
|
|
**Scope:** TO-DOS items 20.0 - 20.10
|
|
**Approach:** TDD — tests define expected behavior, then app code is updated to pass
|
|
**Framework:** Swift Testing (`@Test`, `#expect`, `@Suite`) with XCTest fallback if needed
|
|
**Status:** Use checkboxes to track progress
|
|
|
|
---
|
|
|
|
## Pre-Implementation Setup
|
|
|
|
### Phase 0: Test Infrastructure
|
|
> Set up foundations before writing any feature tests.
|
|
|
|
- [x] **0.1** Create `SportsTimeTests/` directory structure:
|
|
```
|
|
SportsTimeTests/
|
|
├── Fixtures/
|
|
│ └── FixtureGenerator.swift
|
|
├── Mocks/
|
|
│ ├── MockCloudKitService.swift
|
|
│ ├── MockLocationService.swift
|
|
│ └── MockAppDataProvider.swift
|
|
├── Helpers/
|
|
│ ├── BruteForceRouteVerifier.swift
|
|
│ └── TestConstants.swift
|
|
├── Planning/
|
|
│ ├── GameDAGRouterTests.swift
|
|
│ ├── ScenarioAPlannerTests.swift
|
|
│ ├── ScenarioBPlannerTests.swift
|
|
│ ├── ScenarioCPlannerTests.swift
|
|
│ ├── TravelEstimatorTests.swift
|
|
│ ├── ItineraryBuilderTests.swift
|
|
│ └── TripPlanningEngineTests.swift
|
|
└── Performance/
|
|
└── PlannerScaleTests.swift
|
|
```
|
|
|
|
- [x] **0.2** Implement `FixtureGenerator.swift`:
|
|
- Generate synthetic `Game` objects with configurable:
|
|
- Count (5, 50, 500, 2000, 10000)
|
|
- Date range
|
|
- Geographic spread
|
|
- Stadium/team distribution
|
|
- Generate synthetic `Stadium` dictionary
|
|
- Generate synthetic `Trip` with configurable stops
|
|
- Deterministic seeding for reproducible tests
|
|
|
|
- [x] **0.3** Implement `MockCloudKitService.swift`:
|
|
- Stub all public methods
|
|
- Return fixture data
|
|
- Configurable error injection
|
|
|
|
- [x] **0.4** Implement `MockLocationService.swift`:
|
|
- Stub geocoding
|
|
- Stub routing (return pre-calculated distances)
|
|
- Configurable latency simulation
|
|
|
|
- [x] **0.5** Implement `MockAppDataProvider.swift`:
|
|
- Return fixture stadiums/teams/games
|
|
- Configurable to simulate empty data
|
|
|
|
- [x] **0.6** Implement `BruteForceRouteVerifier.swift`:
|
|
- For inputs with ≤8 stops, exhaustively enumerate all permutations
|
|
- Compare engine result against true optimal
|
|
- Used to validate "no obviously better route exists"
|
|
|
|
- [x] **0.7** Implement `TestConstants.swift`:
|
|
```swift
|
|
enum TestConstants {
|
|
static let nearbyRadiusMiles: Double = 50.0
|
|
static let performanceTimeout: TimeInterval = 300.0 // 5 min
|
|
static let hangTimeout: TimeInterval = 30.0
|
|
// Baselines TBD after initial runs
|
|
static var baseline500Games: TimeInterval = 0
|
|
static var baseline2000Games: TimeInterval = 0
|
|
static var baseline10000Games: TimeInterval = 0
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Feature Test Phases
|
|
|
|
### Phase 1: TravelEstimator Tests
|
|
> Foundation — all planners depend on this.
|
|
|
|
**File:** `TravelEstimatorTests.swift`
|
|
|
|
- [x] **1.1** `test_haversineDistanceMiles_KnownDistance`
|
|
NYC to LA = ~2,451 miles (verify within 1% tolerance)
|
|
|
|
- [x] **1.2** `test_haversineDistanceMiles_SamePoint_ReturnsZero`
|
|
|
|
- [x] **1.3** `test_haversineDistanceMiles_Antipodal_ReturnsHalfEarthCircumference`
|
|
|
|
- [x] **1.4** `test_estimate_NilCoordinates_ReturnsNil`
|
|
|
|
- [x] **1.5** `test_estimate_ExceedsMaxDailyHours_ReturnsNil`
|
|
Distance requiring 3+ days of driving should return nil
|
|
|
|
- [x] **1.6** `test_estimate_ValidTrip_ReturnsSegment`
|
|
Verify `distanceMeters`, `durationSeconds`, `travelMode`
|
|
|
|
- [x] **1.7** `test_calculateTravelDays_SingleDayDrive`
|
|
4 hours driving = 1 day
|
|
|
|
- [x] **1.8** `test_calculateTravelDays_MultiDayDrive`
|
|
20 hours driving = 3 days (ceil(20/8))
|
|
|
|
- [x] **1.9** `test_estimateFallbackDistance_SameCity_ReturnsZero`
|
|
|
|
- [x] **1.10** `test_estimateFallbackDistance_DifferentCity_Returns300`
|
|
|
|
---
|
|
|
|
### Phase 2: GameDAGRouter Tests — Core Logic
|
|
> The "scary to touch" component — extensive edge case coverage.
|
|
|
|
**File:** `GameDAGRouterTests.swift`
|
|
|
|
#### 2A: Empty & Single-Element Cases
|
|
|
|
- [x] **2.1** `test_findRoutes_EmptyGames_ReturnsEmptyArray`
|
|
|
|
- [x] **2.2** `test_findRoutes_SingleGame_ReturnsSingleRoute`
|
|
|
|
- [x] **2.3** `test_findRoutes_SingleGame_WithMatchingAnchor_ReturnsSingleRoute`
|
|
|
|
- [x] **2.4** `test_findRoutes_SingleGame_WithNonMatchingAnchor_ReturnsEmpty`
|
|
|
|
#### 2B: Two-Game Cases
|
|
|
|
- [x] **2.5** `test_findRoutes_TwoGames_FeasibleTransition_ReturnsBothInOrder`
|
|
|
|
- [x] **2.6** `test_findRoutes_TwoGames_InfeasibleTransition_ReturnsSeparateRoutes`
|
|
|
|
- [x] **2.7** `test_findRoutes_TwoGames_SameStadiumSameDay_Succeeds`
|
|
(Doubleheader scenario)
|
|
|
|
#### 2C: Anchor Game Constraints
|
|
|
|
- [x] **2.8** `test_findRoutes_WithAnchors_OnlyReturnsRoutesContainingAllAnchors`
|
|
|
|
- [x] **2.9** `test_findRoutes_ImpossibleAnchors_ReturnsEmpty`
|
|
Anchors are geographically/temporally impossible to connect
|
|
|
|
- [x] **2.10** `test_findRoutes_MultipleAnchors_RouteMustContainAll`
|
|
|
|
#### 2D: Repeat Cities Toggle
|
|
|
|
- [x] **2.11** `test_findRoutes_AllowRepeatCities_SameCityMultipleDays_Allowed`
|
|
|
|
- [x] **2.12** `test_findRoutes_DisallowRepeatCities_SkipsSecondVisit`
|
|
|
|
- [x] **2.13** `test_findRoutes_DisallowRepeatCities_OnlyOptionIsRepeat_OverridesWithWarning`
|
|
**TDD Note:** This test defines a new `Trip.warnings: [PlanningWarning]` property
|
|
|
|
#### 2E: Driving Constraints
|
|
|
|
- [x] **2.14** `test_findRoutes_ExceedsMaxDailyDriving_TransitionRejected`
|
|
|
|
- [x] **2.15** `test_findRoutes_MultiDayDrive_Allowed_IfWithinDailyLimits`
|
|
|
|
- [x] **2.16** `test_findRoutes_SameDayDifferentStadiums_ChecksAvailableTime`
|
|
|
|
#### 2F: Calendar Day Logic
|
|
|
|
- [x] **2.17** `test_findRoutes_MaxDayLookahead_RespectsLimit`
|
|
Games > 5 days apart should not connect directly
|
|
|
|
- [x] **2.18** `test_findRoutes_DSTTransition_HandlesCorrectly`
|
|
Spring forward / fall back edge case
|
|
|
|
- [x] **2.19** `test_findRoutes_MidnightGame_AssignsToCorrectDay`
|
|
Game at 12:05 AM belongs to new day
|
|
|
|
#### 2G: Diversity Selection
|
|
|
|
- [x] **2.20** `test_selectDiverseRoutes_ShortAndLongTrips_BothRepresented`
|
|
|
|
- [x] **2.21** `test_selectDiverseRoutes_HighAndLowMileage_BothRepresented`
|
|
|
|
- [x] **2.22** `test_selectDiverseRoutes_FewAndManyCities_BothRepresented`
|
|
|
|
- [x] **2.23** `test_selectDiverseRoutes_DuplicateRoutes_Deduplicated`
|
|
|
|
#### 2H: Cycle Handling
|
|
|
|
- [x] **2.24** `test_findRoutes_GraphWithPotentialCycle_HandlesSilently`
|
|
Verify no infinite loop, returns valid routes
|
|
|
|
#### 2I: Beam Search Behavior
|
|
|
|
- [x] **2.25** `test_findRoutes_LargeDataset_ScalesBeamWidth`
|
|
Verify `effectiveBeamWidth` kicks in for 5000+ games
|
|
|
|
- [x] **2.26** `test_findRoutes_EarlyTermination_TriggersWhenBeamFull`
|
|
|
|
---
|
|
|
|
### Phase 3: GameDAGRouter Tests — Scale & Performance
|
|
> Stress tests for 10K+ objects. Periodic/manual execution.
|
|
|
|
**File:** `GameDAGRouterTests.swift` (continued) or separate `GameDAGRouterScaleTests.swift`
|
|
|
|
#### 3A: Scale Tests
|
|
|
|
- [x] **3.1** `test_findRoutes_5Games_CompletesWithin5Minutes`
|
|
|
|
- [x] **3.2** `test_findRoutes_50Games_CompletesWithin5Minutes`
|
|
|
|
- [x] **3.3** `test_findRoutes_500Games_CompletesWithin5Minutes`
|
|
|
|
- [x] **3.4** `test_findRoutes_2000Games_CompletesWithin5Minutes`
|
|
|
|
- [x] **3.5** `test_findRoutes_10000Games_CompletesWithin5Minutes`
|
|
|
|
- [x] **3.6** `test_findRoutes_50000Nodes_CompletesWithin5Minutes`
|
|
Stress test — may need timeout adjustment
|
|
|
|
#### 3B: Performance Baselines
|
|
|
|
- [x] **3.7** Record baseline times for 500/2000/10000 games (first run)
|
|
|
|
- [x] **3.8** After baselines established, add regression assertions
|
|
|
|
#### 3C: Memory Tests
|
|
|
|
- [x] **3.9** `test_findRoutes_RepeatedCalls_NoMemoryLeak`
|
|
Run 100 iterations, verify allocation/deallocation balance
|
|
|
|
- [x] **3.10** `test_findRoutes_LargeDataset_MemoryBounded`
|
|
10K games should not exceed reasonable memory
|
|
|
|
---
|
|
|
|
### Phase 4: ScenarioAPlanner Tests (Plan by Dates)
|
|
> User provides dates, planner finds games.
|
|
|
|
**File:** `ScenarioAPlannerTests.swift`
|
|
|
|
#### 4A: Valid Inputs
|
|
|
|
- [x] **4.1** `test_planByDates_ValidDateRange_ReturnsGamesInRange`
|
|
|
|
- [x] **4.2** `test_planByDates_SingleDayRange_ReturnsGamesOnThatDay`
|
|
|
|
- [x] **4.3** `test_planByDates_MultiWeekRange_ReturnsMultipleGames`
|
|
|
|
#### 4B: Edge Cases
|
|
|
|
- [x] **4.4** `test_planByDates_NoGamesInRange_ThrowsError`
|
|
**TDD Note:** Uses existing `PlanningFailure.FailureReason.noGamesInRange`
|
|
|
|
- [x] **4.5** `test_planByDates_EndDateBeforeStartDate_ThrowsError`
|
|
|
|
- [x] **4.6** `test_planByDates_SingleGameInRange_ReturnsSingleGameRoute`
|
|
|
|
- [x] **4.7** `test_planByDates_MaxGamesInRange_HandlesGracefully`
|
|
10K games in range — verify no crash/hang
|
|
|
|
#### 4C: Integration with DAG
|
|
|
|
- [x] **4.8** `test_planByDates_UsesDAGRouterForRouting`
|
|
|
|
- [x] **4.9** `test_planByDates_RespectsDriverConstraints`
|
|
|
|
---
|
|
|
|
### Phase 5: ScenarioBPlanner Tests (Must-See Games)
|
|
> User selects specific games, planner builds route.
|
|
|
|
**File:** `ScenarioBPlannerTests.swift`
|
|
|
|
#### 5A: Valid Inputs
|
|
|
|
- [x] **5.1** `test_mustSeeGames_SingleGame_ReturnsTripWithThatGame`
|
|
|
|
- [x] **5.2** `test_mustSeeGames_MultipleGames_ReturnsOptimalRoute`
|
|
|
|
- [x] **5.3** `test_mustSeeGames_GamesInDifferentCities_ConnectsThem`
|
|
|
|
#### 5B: Edge Cases
|
|
|
|
- [x] **5.4** `test_mustSeeGames_EmptySelection_ThrowsError`
|
|
|
|
- [x] **5.5** `test_mustSeeGames_ImpossibleToConnect_ThrowsError`
|
|
Games on same day in cities 850+ miles apart (same region)
|
|
|
|
- [x] **5.6** `test_mustSeeGames_MaxGamesSelected_HandlesGracefully`
|
|
|
|
#### 5C: Optimality Verification
|
|
|
|
- [x] **5.7** `test_mustSeeGames_SmallInput_MatchesBruteForceOptimal`
|
|
≤8 games — verify against `BruteForceRouteVerifier`
|
|
|
|
- [x] **5.8** `test_mustSeeGames_LargeInput_NoObviouslyBetterRoute`
|
|
|
|
---
|
|
|
|
### Phase 6: ScenarioCPlanner Tests (Depart/Return Cities)
|
|
> User specifies origin and destination.
|
|
|
|
**File:** `ScenarioCPlannerTests.swift`
|
|
|
|
#### 6A: Valid Inputs
|
|
|
|
- [x] **6.1** `test_departReturn_SameCity_ReturnsRoundTrip`
|
|
|
|
- [x] **6.2** `test_departReturn_DifferentCities_ReturnsOneWayRoute`
|
|
|
|
- [x] **6.3** `test_departReturn_GamesAlongCorridor_IncludesNearbyGames`
|
|
Uses 50-mile radius
|
|
|
|
#### 6B: Edge Cases
|
|
|
|
- [x] **6.4** `test_departReturn_NoGamesAlongRoute_ThrowsError`
|
|
|
|
- [x] **6.5** `test_departReturn_InvalidCity_ThrowsError`
|
|
|
|
- [x] **6.6** `test_departReturn_ExtremeDistance_RespectsConstraints`
|
|
NYC to LA — verify driving constraints applied
|
|
|
|
#### 6C: Must-Stop Locations
|
|
|
|
- [x] **6.7** `test_departReturn_WithMustStopLocation_IncludesStop`
|
|
|
|
- [x] **6.8** `test_departReturn_MustStopNoNearbyGames_IncludesStopAnyway`
|
|
Stop is included but may not have games
|
|
|
|
- [x] **6.9** `test_departReturn_MultipleMustStops_AllIncluded`
|
|
|
|
- [x] **6.10** `test_departReturn_MustStopConflictsWithRoute_FindsCompromise`
|
|
|
|
---
|
|
|
|
### Phase 7: TripPlanningEngine Integration Tests
|
|
> Main orchestrator — tests all scenarios together.
|
|
|
|
**File:** `TripPlanningEngineTests.swift`
|
|
|
|
#### 7A: Scenario Routing
|
|
|
|
- [x] **7.1** `test_engine_ScenarioA_DelegatesCorrectly`
|
|
|
|
- [x] **7.2** `test_engine_ScenarioB_DelegatesCorrectly`
|
|
|
|
- [x] **7.3** `test_engine_ScenarioC_DelegatesCorrectly`
|
|
|
|
- [x] **7.4** `test_engine_ScenariosAreMutuallyExclusive`
|
|
Cannot mix scenarios in single request
|
|
|
|
#### 7B: Result Structure
|
|
|
|
- [x] **7.5** `test_engine_Result_ContainsTravelSegments`
|
|
|
|
- [x] **7.6** `test_engine_Result_ContainsItineraryDays`
|
|
|
|
- [x] **7.7** `test_engine_Result_IncludesWarnings_WhenApplicable`
|
|
**TDD Note:** Validates `Trip.warnings` property exists
|
|
|
|
#### 7C: Constraint Application
|
|
|
|
- [x] **7.8** `test_engine_NumberOfDrivers_AffectsMaxDailyDriving`
|
|
More drivers = can drive more per day
|
|
|
|
- [x] **7.9** `test_engine_MaxDrivingPerDay_Respected`
|
|
|
|
- [x] **7.10** `test_engine_AllowRepeatCities_PropagatedToDAG`
|
|
|
|
#### 7D: Error Handling
|
|
|
|
- [x] **7.11** `test_engine_ImpossibleConstraints_ReturnsNoResult`
|
|
|
|
- [x] **7.12** `test_engine_EmptyInput_ThrowsError`
|
|
|
|
---
|
|
|
|
### Phase 8: ItineraryBuilder Tests
|
|
> Builds day-by-day itinerary from route.
|
|
|
|
**File:** `ItineraryBuilderTests.swift`
|
|
|
|
- [x] **8.1** `test_builder_SingleGame_CreatesSingleDay`
|
|
|
|
- [x] **8.2** `test_builder_MultiCity_CreatesTravelSegmentsBetween`
|
|
|
|
- [x] **8.3** `test_builder_SameCity_MultipleGames_GroupsOnSameDay`
|
|
|
|
- [x] **8.4** `test_builder_TravelDays_InsertedWhenDrivingExceeds8Hours`
|
|
|
|
- [x] **8.5** `test_builder_ArrivalTimeBeforeGame_Calculated`
|
|
|
|
- [x] **8.6** `test_builder_EmptyRoute_ReturnsEmptyItinerary`
|
|
|
|
---
|
|
|
|
### Phase 9: RouteFilters Tests
|
|
> Filtering on All Trips list.
|
|
|
|
**File:** `RouteFiltersTests.swift`
|
|
|
|
#### 9A: Single Filters
|
|
|
|
- [x] **9.1** `test_filterBySport_SingleSport_ReturnsMatching`
|
|
|
|
- [x] **9.2** `test_filterBySport_MultipleSports_ReturnsUnion`
|
|
|
|
- [x] **9.3** `test_filterBySport_AllSports_ReturnsAll`
|
|
|
|
- [x] **9.4** `test_filterByDateRange_ReturnsTripsInRange`
|
|
(+ bonus: `test_filterByDateRange_IncludesOverlappingTrips`)
|
|
|
|
- [x] **9.5** `test_filterByStatus_Planned_ReturnsPlanned`
|
|
**TDD Note:** `Trip.status: TripStatus` property added
|
|
|
|
- [x] **9.6** `test_filterByStatus_InProgress_ReturnsInProgress`
|
|
|
|
- [x] **9.7** `test_filterByStatus_Completed_ReturnsCompleted`
|
|
|
|
#### 9B: Combined Filters
|
|
|
|
- [x] **9.8** `test_combinedFilters_SportAndDate_ReturnsIntersection`
|
|
|
|
- [x] **9.9** `test_combinedFilters_AllFilters_ReturnsIntersection`
|
|
|
|
#### 9C: Edge Cases
|
|
|
|
- [x] **9.10** `test_filter_NoMatches_ReturnsEmptyArray`
|
|
|
|
- [x] **9.11** `test_filter_AllMatch_ReturnsAll`
|
|
|
|
- [x] **9.12** `test_filter_EmptyInput_ReturnsEmptyArray`
|
|
|
|
---
|
|
|
|
### Phase 10: Concurrency Tests
|
|
> Prove current implementation is NOT thread-safe (for future work).
|
|
|
|
**File:** `ConcurrencyTests.swift`
|
|
|
|
- [x] **10.1** `test_engine_ConcurrentRequests_CurrentlyUnsafe`
|
|
Document existing behavior (may crash/race)
|
|
|
|
- [x] **10.2** `test_engine_SequentialRequests_Succeeds`
|
|
|
|
**Future (out of scope for now):**
|
|
- [ ] `test_engine_ConcurrentRequests_ThreadSafe` (after refactor)
|
|
|
|
---
|
|
|
|
### Phase 11: Edge Case Omnibus
|
|
> Catch-all for extreme/unusual inputs.
|
|
|
|
**File:** `EdgeCaseTests.swift`
|
|
|
|
#### 11A: Data Edge Cases
|
|
|
|
- [x] **11.1** `test_nilStadium_HandlesGracefully`
|
|
|
|
- [x] **11.2** `test_malformedDate_HandlesGracefully`
|
|
|
|
- [x] **11.3** `test_invalidCoordinates_HandlesGracefully`
|
|
Lat > 90, Lon > 180
|
|
|
|
- [x] **11.4** `test_missingRequiredFields_HandlesGracefully`
|
|
|
|
#### 11B: Boundary Conditions
|
|
|
|
- [x] **11.5** `test_exactlyAtDrivingLimit_Succeeds`
|
|
|
|
- [x] **11.6** `test_oneMileOverLimit_Fails`
|
|
|
|
- [x] **11.7** `test_exactlyAtRadiusBoundary_IncludesGame`
|
|
Game at exactly 50 miles
|
|
|
|
- [x] **11.8** `test_oneFootOverRadius_ExcludesGame`
|
|
|
|
#### 11C: Time Zone Cases
|
|
|
|
- [x] **11.9** `test_gameInDifferentTimeZone_NormalizesToUTC`
|
|
|
|
- [x] **11.10** `test_dstSpringForward_HandlesCorrectly`
|
|
|
|
- [x] **11.11** `test_dstFallBack_HandlesCorrectly`
|
|
|
|
---
|
|
|
|
## API Proposals (TDD Discoveries)
|
|
|
|
These APIs will be defined by tests and need implementation:
|
|
|
|
| Property/Type | Defined In | Description |
|
|
|--------------|------------|-------------|
|
|
| `Trip.warnings: [PlanningWarning]` | 2.13 | Warnings when planner overrides preferences |
|
|
| `PlanningWarning` enum | 2.13 | `.repeatCityOverridden(city: String)`, etc. |
|
|
| `PlanningError.noGamesFound` | 4.4 | Thrown when date range has no games |
|
|
| `Trip.status: TripStatus` | 9.5 | `.planned`, `.inProgress`, `.completed` |
|
|
|
|
---
|
|
|
|
## Execution Order
|
|
|
|
**Recommended batch order for TDD cycle:**
|
|
|
|
1. **Phase 0** — Infrastructure (no app changes)
|
|
2. **Phase 1** — TravelEstimator (foundation, likely passes)
|
|
3. **Phase 2** — GameDAGRouter core (highest risk, most edge cases)
|
|
4. **Phase 3** — GameDAGRouter scale (set baselines)
|
|
5. **Phase 4-6** — Scenario planners (A, B, C)
|
|
6. **Phase 7** — TripPlanningEngine integration
|
|
7. **Phase 8** — ItineraryBuilder
|
|
8. **Phase 9** — RouteFilters
|
|
9. **Phase 10** — Concurrency (documentation tests)
|
|
10. **Phase 11** — Edge cases
|
|
|
|
---
|
|
|
|
## Progress Tracking
|
|
|
|
| Phase | Tests | Passing | Status |
|
|
|-------|-------|---------|--------|
|
|
| 0 | 7 | 7 | Complete |
|
|
| 1 | 10 | 10 | Complete |
|
|
| 2 | 26 | 26 | Complete |
|
|
| 3 | 10 | 10 | Complete |
|
|
| 4 | 9 | 9 | Complete |
|
|
| 5 | 8 | 8 | Complete |
|
|
| 6 | 10 | 10 | Complete |
|
|
| 7 | 12 | 12 | Complete |
|
|
| 8 | 6 | 6 | Complete |
|
|
| 9 | 13 | 13 | Complete |
|
|
| 10 | 2 | 2 | Complete |
|
|
| 11 | 11 | 11 | Complete |
|
|
| **Total** | **124** | **124** | |
|
|
|
|
---
|
|
|
|
## Notes
|
|
|
|
- **Hang timeout:** 30 seconds (tests marked as hanging if exceeded)
|
|
- **Performance timeout:** 5 minutes per test (scale tests)
|
|
- **Nearby radius:** 50 miles driving distance (`TestConstants.nearbyRadiusMiles`)
|
|
- **Brute force threshold:** ≤8 stops for exact optimality verification
|
|
- **Baselines:** Will be recorded after initial runs, then hardcoded
|
|
|
|
---
|
|
|
|
*Last updated: 2026-01-11 (Phase 11 complete — All tests passing)*
|