Golang程序测试指南与最佳实践
Golang程序测试指南与最佳实践
func TestAvg2(t *testing.T) {
type test struct {
data []float64
answer float64
}
tests := []test{
test{[]float64{2, 2}, 2.00},
test{[]float64{4, 4}, 4.00},
test{[]float64{3, 3, 4}, 3.33},
test{[]float64{3, 3, 5}, 3.67},
test{[]float64{5, 5, 5}, 5.00},
test{[]float64{-10, 10, 10, 11}, 5.25},
}
for _, v := range tests {
x := Avg(v.data...)
str := fmt.Sprintf("%.2f", x)
fl, _ := strconv.ParseFloat(str, 64)
if x != v.answer {
t.Error("Expected", v.answer, "got", fl)
}
}
}
结果: table_test.go:29: Expected 3.33 got 3.33 table_test.go:29: Expected 3.67 got 3.67
哪里出错了?
更多关于Golang程序测试指南与最佳实践的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
舍入误差。这是浮点数众所周知的特性。
对于浮点数,通常检查两个值之间差值的绝对值是否小于或等于某个阈值,如果差值足够小,则认为它们相等。
更多关于Golang程序测试指南与最佳实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
问题出在浮点数精度比较上。使用 != 直接比较浮点数会导致精度问题,即使显示值相同,底层二进制表示可能不同。
以下是修复后的测试代码:
func TestAvg2(t *testing.T) {
type test struct {
data []float64
answer float64
}
tests := []test{
{[]float64{2, 2}, 2.00},
{[]float64{4, 4}, 4.00},
{[]float64{3, 3, 4}, 3.33},
{[]float64{3, 3, 5}, 3.67},
{[]float64{5, 5, 5}, 5.00},
{[]float64{-10, 10, 10, 11}, 5.25},
}
for _, v := range tests {
x := Avg(v.data...)
// 使用容差比较浮点数
if math.Abs(x-v.answer) > 0.01 {
t.Errorf("Expected %.2f, got %.2f", v.answer, x)
}
}
}
或者使用 cmp.Diff 进行更精确的比较:
import "github.com/google/go-cmp/cmp"
func TestAvg2(t *testing.T) {
type test struct {
data []float64
answer float64
}
tests := []test{
{[]float64{2, 2}, 2.00},
{[]float64{4, 4}, 4.00},
{[]float64{3, 3, 4}, 3.33},
{[]float64{3, 3, 5}, 3.67},
{[]float64{5, 5, 5}, 5.00},
{[]float64{-10, 10, 10, 11}, 5.25},
}
for _, v := range tests {
x := Avg(v.data...)
// 使用cmp.Comparer定义浮点数比较容差
opt := cmp.Comparer(func(x, y float64) bool {
return math.Abs(x-y) <= 0.01
})
if diff := cmp.Diff(v.answer, x, opt); diff != "" {
t.Errorf("Mismatch (-want +got):\n%s", diff)
}
}
}
对于测试表格,推荐使用子测试:
func TestAvg2(t *testing.T) {
tests := []struct {
name string
data []float64
want float64
}{
{"two equal numbers", []float64{2, 2}, 2.00},
{"another two equal", []float64{4, 4}, 4.00},
{"three numbers with decimal", []float64{3, 3, 4}, 3.33},
{"three numbers with different decimal", []float64{3, 3, 5}, 3.67},
{"all same numbers", []float64{5, 5, 5}, 5.00},
{"mixed positive negative", []float64{-10, 10, 10, 11}, 5.25},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Avg(tt.data...)
if math.Abs(got-tt.want) > 0.01 {
t.Errorf("Avg() = %.2f, want %.2f", got, tt.want)
}
})
}
}
浮点数比较应该始终使用容差(epsilon)值,而不是直接相等比较。

