实用科技屋
霓虹主题四 · 更硬核的阅读氛围

Go语言测试怎么写:从零开始实战案例

发布时间:2026-01-23 05:41:22 阅读:170 次

Go语言测试怎么写:一个实际项目的入门路径

在开发一个小型订单系统时,我需要确保每个函数都能正确处理用户提交的数据。这时候,写测试就不是可选项,而是必需品。Go语言自带的 testing 包足够轻量又实用,不用额外引入框架也能把事办好。

比如有一个计算订单总价的函数,输入是商品价格列表,输出是总金额。这个逻辑看着简单,但一旦涉及折扣、税费,出错概率就上来了。为了防止改一处崩一片,我决定给它加上单元测试。

测试文件怎么命名

Go 的约定很明确:被测文件叫 order.go,测试文件就得叫 order_test.go,放在同一个包里。测试函数必须以 Test 开头,参数是 *testing.T。就这么点规则,清清楚楚。

func TestCalculateTotal(t *testing.T) {
prices := []float64{10.5, 20.0, 15.3}
total := CalculateTotal(prices)
expected := 45.8

if total != expected {
t.Errorf("期望 %.2f,但得到 %.2f", expected, total)
}
}

写完后,在命令行运行 go test,就能看到结果。如果测试通过,啥也不用管;失败了,t.Errorf 会告诉你哪一行出了问题。

表驱动测试让用例更清晰

随着业务变复杂,订单可能有满减、会员折扣等不同场景。一个个写 Test 函数太重复。这时用表驱动测试(table-driven test)更高效。

func TestCalculateTotalWithDiscount(t *testing.T) {
tests := []struct {
name string
prices []float64
hasVIP bool
expected float64
}{
{"普通用户无折扣", []float64{10, 20}, false, 30},
{"VIP用户享9折", []float64{10, 20}, true, 27},
{"空列表应返回0", nil, false, 0},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := CalculateTotalWithDiscount(tt.prices, tt.hasVIP)
if result != tt.expected {
t.Errorf("期望 %.2f,但得到 %.2f", tt.expected, result)
}
})
}
}

每个测试用例像表格一样列出来,结构清晰,加新用例也方便。配合 t.Run,还能看到具体哪个子测试失败,排查起来不抓瞎。

覆盖率不是目标,但能提醒你漏了啥

跑完测试后,可以用 go test -cover 看覆盖率。80% 不是硬指标,但如果你发现某个分支从来没测到,比如退货退款的边界情况,这就是个提醒。

有时候为了高覆盖率写一堆无意义的测试反而浪费时间。关键是核心逻辑有没有覆盖到位。比如订单金额不能为负,这种判断就得有对应测试。

测试也要保持简洁和可读

别把测试写得太复杂。测试代码也是代码,别人要能看懂你在验证什么。变量命名清楚,比如 expectedactual,错误信息写具体点,别只说“结果不对”。

项目上线前跑一遍 go test ./...,所有包的测试都执行一遍,心里踏实多了。特别是重构函数的时候,测试就是你的安全带。

写 Go 测试不需要学太多花哨的东西,把基础用熟,配合项目节奏逐步加上,慢慢就成了开发习惯的一部分。