test(backend): 添加核心计算单测与 Statistics 业务单测
Phase 1.4。AGENTS.md §19 与 plan §6 都把单测作为 MVP 硬要求,这条 commit
把核心计算覆盖完毕。
新增:
- pkg/decimal/money_test.go 5 个函数 × table-driven,共 22 个子测试
* PricePerLiter:覆盖 plan §6.1 的 176.33/23.67 = 7.45,以及简单整数除、
liters<=0 边界、四位精度等
* ConsumptionL100km:覆盖 plan §6.3 的 (10500-10000)/40*100 = 8.0,以及
mileage<=0 边界
* CostPerKm:覆盖 plan §6.4 的 256/500 = 0.512
* Mileage:正常递增 / 相等(没开) / 倒推(里程倒写,应为 0) / 首次记录(prev=0)
* AvgFloat64:空切片 / 单值 / 多值 / 舍入
- internal/service/refuel_record_test.go 5 个测试,覆盖 plan §6.3 的
"半箱油不进入标准油耗"硬规则
* TestStatistics_TwoConsecutiveFull:两条 is_full → mileage=500,
consumption=8.0, cost=0.64, 命中 plan 案例
* TestStatistics_HalfTankDoesNotPollute:两条全 + 一条半箱,标准油耗仍 8.0,
半箱油被正确跳过
* TestStatistics_OnlyHalfTanks:全是半箱,标准油耗 = 0(没采样)
* TestStatistics_MultipleFullSamples:三条全,平均油耗/成本正确
* TestStatistics_EmptyVehicle:零记录时 LastRefuel 应为 nil
测试方法:
- 纯单测,不接 SQLite,自己写 fakeVehicleRepo / fakeRefuelRepo
实现 repository 接口;fake 也按 refuel_time DESC 排,与真 repo 行为一致
- sentinel 错误与 apperror.IsCode 风格一致,后续接 apperror 时改一行即可
期间踩到的一个坑(已修):
- 第一版 fake ListByVehicle 不排序,Statistics 倒序迭代拿到错误顺序,
mileage 算成负 → 全部回 0。修法:fake 加上 sort.Slice DESC,与真 repo 对齐
验证:
go vet ./... 0 issues
go test ./pkg/decimal ./internal/service
ok pkg/decimal 22 子测试通过
ok internal/service 5 测试通过
未做(留待后续):
- handler 单测(纯 HTTP 表层,可加,目前 smoke.ps1 已覆盖)
- repository 单测(需要 sqlite,end-to-end smoke 已经覆盖)
- CI 接入(留到 Phase 1.5 之后用 GitHub Actions / Gitea Actions)