fix(tests): derive fee test expectations from constants, not hardcoded values
All checks were successful
Deploy to K8s / deploy (push) Successful in 9s

Configured-month cases now read expected values from AdultFeeMonthlyRate /
JuniorFeeMonthlyRate via a mustRate helper that panics if a test month is
removed from the map. Fallback cases use AdultFeeDefault / JuniorFeeDefault.

This way the tests verify dispatch logic (0/1/2+ branching, map vs. fallback)
without breaking when rates are intentionally updated in the map.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 11:37:52 +02:00
parent 6f2994b8ad
commit f047150004
2 changed files with 47 additions and 18 deletions

View File

@@ -5,24 +5,40 @@ import "testing"
func TestCalculateFee(t *testing.T) { func TestCalculateFee(t *testing.T) {
t.Parallel() t.Parallel()
// All expected outputs verified against live Python implementation on 2026-05-06: // mustRate returns the configured rate for a month that must be in the map.
// PYTHONPATH=scripts:. python -c 'from attendance import calculate_fee; print([calculate_fee(c,m) for c,m in [(0,"2026-05"),(0,""),(1,"2026-05"),(1,"unknown"),(2,"2026-05"),(2,"2026-03"),(2,"2025-09"),(5,"2026-05"),(2,"2027-01"),(2,"")]])' // It panics immediately if the month is absent — so if a rate entry is ever
// removed, the test fails loudly rather than silently comparing against
// Go's zero value.
mustRate := func(month string) int {
r, ok := AdultFeeMonthlyRate[month]
if !ok {
panic("test month not in AdultFeeMonthlyRate: " + month)
}
return r
}
tests := []struct { tests := []struct {
name string name string
count int count int
month string month string
want int want int
}{ }{
// Zero attendance always returns 0.
{"zero short-circuits", 0, "2026-05", 0}, {"zero short-circuits", 0, "2026-05", 0},
{"zero empty month", 0, "", 0}, {"zero empty month", 0, "", 0},
{"single practice", 1, "2026-05", 200}, // Single practice returns AdultFeeSingle regardless of month.
{"single ignores monthKey", 1, "unknown", 200}, {"single practice", 1, "2026-05", AdultFeeSingle},
{"two practices configured month", 2, "2026-05", 700}, {"single ignores monthKey", 1, "unknown", AdultFeeSingle},
{"two practices reduced march", 2, "2026-03", 350}, // Two+ practices for a configured month: must use the map value, not the default.
{"two practices early season", 2, "2025-09", 750}, // Expected values are read from AdultFeeMonthlyRate so this test stays correct
{"high count same as two", 5, "2026-05", 700}, // when rates are updated — the assertion verifies dispatch logic, not rate values.
{"unknown future month falls back", 2, "2027-01", 700}, {"two practices configured month", 2, "2026-05", mustRate("2026-05")},
{"empty month falls back", 2, "", 700}, {"two practices reduced march", 2, "2026-03", mustRate("2026-03")},
{"two practices early season", 2, "2025-09", mustRate("2025-09")},
{"high count same as two", 5, "2026-05", mustRate("2026-05")},
// Two+ practices for an unknown/future month: must fall back to AdultFeeDefault.
{"unknown future month falls back", 2, "2027-01", AdultFeeDefault},
{"empty month falls back", 2, "", AdultFeeDefault},
} }
for _, tc := range tests { for _, tc := range tests {

View File

@@ -5,24 +5,37 @@ import "testing"
func TestCalculateJuniorFee(t *testing.T) { func TestCalculateJuniorFee(t *testing.T) {
t.Parallel() t.Parallel()
// All expected outputs verified against live Python implementation on 2026-05-06: // mustRate returns the configured rate for a month that must be in the map.
// PYTHONPATH=scripts:. python -c 'from attendance import calculate_junior_fee; print([calculate_junior_fee(c,m) for c,m in [(0,"2026-05"),(0,""),(1,"2026-05"),(1,"unknown"),(2,"2026-05"),(2,"2025-09"),(2,"2026-03"),(5,"2025-09"),(2,"2027-01"),(2,"")]])' // Panics immediately if the month is absent so a removed entry causes a loud
// failure rather than a silent comparison against Go's zero value.
mustRate := func(month string) Expected {
r, ok := JuniorFeeMonthlyRate[month]
if !ok {
panic("test month not in JuniorFeeMonthlyRate: " + month)
}
return Expected{Value: r}
}
tests := []struct { tests := []struct {
name string name string
count int count int
month string month string
want Expected want Expected
}{ }{
// Zero attendance always returns 0.
{"zero short-circuits", 0, "2026-05", Expected{Value: 0}}, {"zero short-circuits", 0, "2026-05", Expected{Value: 0}},
{"zero empty month", 0, "", Expected{Value: 0}}, {"zero empty month", 0, "", Expected{Value: 0}},
// Single practice returns the Unknown sentinel regardless of month.
{"single practice sentinel", 1, "2026-05", Expected{Unknown: true}}, {"single practice sentinel", 1, "2026-05", Expected{Unknown: true}},
{"single ignores monthKey", 1, "unknown", Expected{Unknown: true}}, {"single ignores monthKey", 1, "unknown", Expected{Unknown: true}},
{"two practices default month", 2, "2026-05", Expected{Value: 500}}, // Two+ practices for a configured month: must use the map value, not the default.
{"two practices reduced sept", 2, "2025-09", Expected{Value: 250}}, {"two practices unconfigured month", 2, "2026-05", Expected{Value: JuniorFeeDefault}},
{"two practices reduced march", 2, "2026-03", Expected{Value: 250}}, {"two practices reduced sept", 2, "2025-09", mustRate("2025-09")},
{"high count same as two", 5, "2025-09", Expected{Value: 250}}, {"two practices reduced march", 2, "2026-03", mustRate("2026-03")},
{"unknown future month falls back", 2, "2027-01", Expected{Value: 500}}, {"high count same as two", 5, "2025-09", mustRate("2025-09")},
{"empty month falls back", 2, "", Expected{Value: 500}}, // Two+ practices for an unknown/future month: must fall back to JuniorFeeDefault.
{"unknown future month falls back", 2, "2027-01", Expected{Value: JuniorFeeDefault}},
{"empty month falls back", 2, "", Expected{Value: JuniorFeeDefault}},
} }
for _, tc := range tests { for _, tc := range tests {