为什么需要单元测试
开发一个功能时,比如计算订单总价,改着改着可能把原来的逻辑搞坏了。手动点来点去验证太麻烦,还容易漏。这时候单元测试就派上用场了——它像个小机器人,每次代码一动,它就自动跑一遍检查,哪里出问题马上告诉你。
在 Go 语言里写单元测试特别简单,标准库自带支持,不用额外装工具。
测试文件怎么写
假设你有个文件叫 calculator.go,里面有个函数用来加两个数:
package main
func Add(a, b int) int {
return a + b
}那对应的测试文件就是 calculator_test.go,名字要以 _test.go 结尾:
package main
import (
"testing"
)
func TestAdd(t *testing.T) {
result := Add(2, 3)
expected := 5
if result != expected {
t.Errorf("期望 %d,但得到了 %d", expected, result)
}
}写完后,在终端运行 go test,就能看到结果。如果输出 OK,说明通过;如果有错,会提示哪一行不符合预期。
测试多个场景
一个函数往往有多种输入情况。比如减法函数,不仅要测正数,还要测负数、零:
func Subtract(a, b int) int {
return a - b
}
func TestSubtract(t *testing.T) {
cases := []struct {
a, b int
expected int
}{
{10, 5, 5},
{5, 10, -5},
{0, 0, 0},
{-1, -1, 0},
}
for _, c := range cases {
result := Subtract(c.a, c.b)
if result != c.expected {
t.Errorf("Subtract(%d, %d) = %d, 期望 %d", c.a, c.b, result, c.expected)
}
}
}这种写法把多个测试用例集中在一起,以后加新情况也方便。
测试覆盖率怎么看
写完测试,可以看看这些测试到底覆盖了多少代码。运行命令:
go test -cover会输出类似 coverage: 85.7% of statements 的信息。想看更详细的报告,可以生成 HTML:
go test -coverprofile=cover.out
go tool cover -html=cover.out浏览器会打开一个页面,绿色是被测到的代码,红色是没覆盖到的部分。你可以盯着红的地方补测试,让项目更稳。
实际项目中的小技巧
在 Web 服务中,经常要测处理 HTTP 请求的函数。可以用 net/http/httptest 模拟请求:
package main
import (
"net/http"
"net/http/httptest"
"testing"
)
func HelloHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
}
func TestHelloHandler(t *testing.T) {
req := httptest.NewRequest("GET", "/hello", nil)
w := httptest.NewRecorder()
HelloHandler(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusOK {
t.Errorf("状态码不是 200")
}
body := w.Body.String()
if body != "Hello, World!" {
t.Errorf("响应体不符: %s", body)
}
}这样不用真正启动服务器也能验证接口行为,速度快,适合集成进自动化流程。
团队协作时,很多人提交代码前都会跑一遍测试。CI 系统(比如 GitHub Actions)也能自动执行 go test,通不过就不让合并,避免把问题带进主干。