refactor(tests): TDD rewrite of all unit tests with spec documentation
Complete rewrite of unit test suite using TDD methodology: Planning Engine Tests: - GameDAGRouterTests: Beam search, anchor games, transitions - ItineraryBuilderTests: Stop connection, validators, EV enrichment - RouteFiltersTests: Region, time window, scoring filters - ScenarioA/B/C/D PlannerTests: All planning scenarios - TravelEstimatorTests: Distance, duration, travel days - TripPlanningEngineTests: Orchestration, caching, preferences Domain Model Tests: - AchievementDefinitionsTests, AnySportTests, DivisionTests - GameTests, ProgressTests, RegionTests, StadiumTests - TeamTests, TravelSegmentTests, TripTests, TripPollTests - TripPreferencesTests, TripStopTests, SportTests Service Tests: - FreeScoreAPITests, RouteDescriptionGeneratorTests - SuggestedTripsGeneratorTests Export Tests: - ShareableContentTests (card types, themes, dimensions) Bug fixes discovered through TDD: - ShareCardDimensions: mapSnapshotSize exceeded available width (960x480) - ScenarioBPlanner: Added anchor game validation filter All tests include: - Specification tests (expected behavior) - Invariant tests (properties that must always hold) - Edge case tests (boundary conditions) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
164
SportsTimeTests/Domain/RegionTests.swift
Normal file
164
SportsTimeTests/Domain/RegionTests.swift
Normal file
@@ -0,0 +1,164 @@
|
||||
//
|
||||
// RegionTests.swift
|
||||
// SportsTimeTests
|
||||
//
|
||||
// TDD specification tests for Region enum.
|
||||
//
|
||||
|
||||
import Testing
|
||||
@testable import SportsTime
|
||||
|
||||
@Suite("Region")
|
||||
struct RegionTests {
|
||||
|
||||
// MARK: - Specification Tests: classify(longitude:)
|
||||
|
||||
@Test("classify: longitude > -85 returns .east")
|
||||
func classify_east() {
|
||||
// NYC: -73.9855
|
||||
#expect(Region.classify(longitude: -73.9855) == .east)
|
||||
|
||||
// Boston: -71.0972
|
||||
#expect(Region.classify(longitude: -71.0972) == .east)
|
||||
|
||||
// Miami: -80.1918
|
||||
#expect(Region.classify(longitude: -80.1918) == .east)
|
||||
|
||||
// Toronto: -79.3832
|
||||
#expect(Region.classify(longitude: -79.3832) == .east)
|
||||
|
||||
// Atlanta: -84.3880
|
||||
#expect(Region.classify(longitude: -84.3880) == .east)
|
||||
|
||||
// Just above boundary
|
||||
#expect(Region.classify(longitude: -84.9999) == .east)
|
||||
}
|
||||
|
||||
@Test("classify: longitude in -110...-85 returns .central")
|
||||
func classify_central() {
|
||||
// Chicago: -87.6233
|
||||
#expect(Region.classify(longitude: -87.6233) == .central)
|
||||
|
||||
// Houston: -95.3698
|
||||
#expect(Region.classify(longitude: -95.3698) == .central)
|
||||
|
||||
// Dallas: -96.7970
|
||||
#expect(Region.classify(longitude: -96.7970) == .central)
|
||||
|
||||
// Minneapolis: -93.2650
|
||||
#expect(Region.classify(longitude: -93.2650) == .central)
|
||||
|
||||
// Denver: -104.9903
|
||||
#expect(Region.classify(longitude: -104.9903) == .central)
|
||||
|
||||
// Boundary: exactly -85
|
||||
#expect(Region.classify(longitude: -85.0) == .central)
|
||||
|
||||
// Boundary: exactly -110
|
||||
#expect(Region.classify(longitude: -110.0) == .central)
|
||||
}
|
||||
|
||||
@Test("classify: longitude < -110 returns .west")
|
||||
func classify_west() {
|
||||
// Los Angeles: -118.2673
|
||||
#expect(Region.classify(longitude: -118.2673) == .west)
|
||||
|
||||
// San Francisco: -122.4194
|
||||
#expect(Region.classify(longitude: -122.4194) == .west)
|
||||
|
||||
// Seattle: -122.3321
|
||||
#expect(Region.classify(longitude: -122.3321) == .west)
|
||||
|
||||
// Phoenix: -112.0740
|
||||
#expect(Region.classify(longitude: -112.0740) == .west)
|
||||
|
||||
// Las Vegas: -115.1398
|
||||
#expect(Region.classify(longitude: -115.1398) == .west)
|
||||
|
||||
// Just below boundary
|
||||
#expect(Region.classify(longitude: -110.0001) == .west)
|
||||
}
|
||||
|
||||
// MARK: - Specification Tests: Boundary Values
|
||||
|
||||
@Test("classify boundary: -85 is central, -84.9999 is east")
|
||||
func classify_eastCentralBoundary() {
|
||||
#expect(Region.classify(longitude: -85.0) == .central)
|
||||
#expect(Region.classify(longitude: -84.9999) == .east)
|
||||
#expect(Region.classify(longitude: -85.0001) == .central)
|
||||
}
|
||||
|
||||
@Test("classify boundary: -110 is central, -110.0001 is west")
|
||||
func classify_centralWestBoundary() {
|
||||
#expect(Region.classify(longitude: -110.0) == .central)
|
||||
#expect(Region.classify(longitude: -109.9999) == .central)
|
||||
#expect(Region.classify(longitude: -110.0001) == .west)
|
||||
}
|
||||
|
||||
// MARK: - Specification Tests: Edge Cases
|
||||
|
||||
@Test("classify: extreme east longitude (positive) returns .east")
|
||||
func classify_extremeEast() {
|
||||
#expect(Region.classify(longitude: 0.0) == .east)
|
||||
#expect(Region.classify(longitude: 50.0) == .east)
|
||||
}
|
||||
|
||||
@Test("classify: extreme west longitude returns .west")
|
||||
func classify_extremeWest() {
|
||||
#expect(Region.classify(longitude: -180.0) == .west)
|
||||
#expect(Region.classify(longitude: -150.0) == .west)
|
||||
}
|
||||
|
||||
// MARK: - Invariant Tests
|
||||
|
||||
@Test("Invariant: classify never returns .crossCountry")
|
||||
func invariant_classifyNeverReturnsCrossCountry() {
|
||||
let testLongitudes: [Double] = [-180, -150, -120, -110.0001, -110, -100, -85.0001, -85, -70, 0, 50]
|
||||
for lon in testLongitudes {
|
||||
let region = Region.classify(longitude: lon)
|
||||
#expect(region != .crossCountry, "classify should never return crossCountry for longitude \(lon)")
|
||||
}
|
||||
}
|
||||
|
||||
@Test("Invariant: every longitude maps to exactly one region")
|
||||
func invariant_everyLongitudeMapsToOneRegion() {
|
||||
// Test a range of longitudes
|
||||
for lon in stride(from: -180.0, through: 50.0, by: 10.0) {
|
||||
let region = Region.classify(longitude: lon)
|
||||
#expect([Region.east, .central, .west].contains(region), "Longitude \(lon) should map to east, central, or west")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Property Tests
|
||||
|
||||
@Test("Property: id equals rawValue")
|
||||
func property_idEqualsRawValue() {
|
||||
for region in Region.allCases {
|
||||
#expect(region.id == region.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
@Test("Property: displayName equals rawValue")
|
||||
func property_displayNameEqualsRawValue() {
|
||||
for region in Region.allCases {
|
||||
#expect(region.displayName == region.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
@Test("Property: all regions have iconName")
|
||||
func property_allRegionsHaveIconName() {
|
||||
for region in Region.allCases {
|
||||
#expect(!region.iconName.isEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Specification Tests: Display Properties
|
||||
|
||||
@Test("shortName values are correct")
|
||||
func shortName_values() {
|
||||
#expect(Region.east.shortName == "East")
|
||||
#expect(Region.central.shortName == "Central")
|
||||
#expect(Region.west.shortName == "West")
|
||||
#expect(Region.crossCountry.shortName == "Coast to Coast")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user