// forecast_test.go - Unit tests (example) package main import ( "math" "testing" "time" ) func TestCalculateFeelsLike(t *testing.T) { tests := []struct { name string temp float64 humidity float64 windSpeed float64 want float64 }{ {"Cold with wind", 5, 80, 10, 0.49}, // Approximate wind chill {"Warm with humidity", 30, 80, 5, 32.65}, // Approximate heat index {"Moderate", 20, 50, 5, 20}, // No adjustment } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := CalculateFeelsLike(tt.temp, tt.humidity, tt.windSpeed) if math.Abs(got-tt.want) > 1.0 { // Allow 1 degree tolerance t.Errorf("CalculateFeelsLike() = %v, want %v", got, tt.want) } }) } } func TestWeatherMapper(t *testing.T) { mapper := NewWeatherMapper() sunrise := time.Date(2026, 2, 1, 8, 0, 0, 0, time.UTC) sunset := time.Date(2026, 2, 1, 16, 0, 0, 0, time.UTC) tests := []struct { symbol int time time.Time wantID int wantIcon string }{ {1, sunrise.Add(2 * time.Hour), 800, "01d"}, // Clear, daytime {1, sunset.Add(2 * time.Hour), 800, "01n"}, // Clear, nighttime {25, sunrise, 500, "10d"}, // Light rain, daytime {91, sunset, 200, "11n"}, // Thunderstorm, nighttime } for _, tt := range tests { t.Run("", func(t *testing.T) { weather := mapper.Map(tt.symbol, tt.time, sunrise, sunset) if weather.ID != tt.wantID { t.Errorf("Weather.ID = %v, want %v", weather.ID, tt.wantID) } if weather.Icon != tt.wantIcon { t.Errorf("Weather.Icon = %v, want %v", weather.Icon, tt.wantIcon) } }) } } func TestSunCalculator(t *testing.T) { calculator := NewSunCalculator(60.169, 24.935, 2) // Helsinki date := time.Date(2026, 2, 1, 0, 0, 0, 0, time.UTC) sunrise, sunset, err := calculator.Calculate(date) if err != nil { t.Errorf("SunCalculator.Calculate() error = %v", err) } if sunrise.IsZero() || sunset.IsZero() { t.Errorf("Sunrise or sunset is zero") } // Sunrise should be before sunset if !sunrise.Before(sunset) { t.Errorf("Sunrise %v not before sunset %v", sunrise, sunset) } }