Golang测试失败问题排查:函数返回预期结果但测试不通过

Golang测试失败问题排查:函数返回预期结果但测试不通过

package sqrt

func Sqrt(num int64) float64 {
	const precision = 0.001

	i := int64(1)
	for ; i*i <= num; i++ {
	}
	result := float64(i - 1)

	for ; result*result <= float64(num); result += precision {

	}
	return result - precision
}
package sqrt

import "testing"

var sqrtTests = []struct {
	num    int64
	result float64
}{
	{9, 3.0},
	{10, 3.162},
	{5, 2.236},
	{97, 9.848},
	{16, 4.0},
}

func TestSqrt(t *testing.T) {
	for _, tt := range sqrtTests {
		if got := Sqrt(tt.num); got != tt.result {
			t.Errorf("got: Sqrt(%d)=%f, want: Sqrt(%d)=%f", tt.num, got, tt.num, tt.result)
		}
	}
}
[okumar@oshank-pc:sqrt]🎩 go test 
--- FAIL: TestSqrt (0.00s)
    sqrt_test.go:19: got: Sqrt(10)=3.162000, want: Sqrt(10)=3.162000
    sqrt_test.go:19: got: Sqrt(5)=2.236000, want: Sqrt(5)=2.236000
    sqrt_test.go:19: got: Sqrt(97)=9.848000, want: Sqrt(97)=9.848000
FAIL
exit status 1
FAIL    <http://github.com/oshankfriends/go-examples/sqrt|github.com/oshankfriends/go-examples/sqrt>       0.001s

更多关于Golang测试失败问题排查:函数返回预期结果但测试不通过的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

差异可能隐藏在删除的部分之后。我们不应该使用等值比较符来比较浮点数。

应该检查它们是否在目标值的允许误差范围内。

更多关于Golang测试失败问题排查:函数返回预期结果但测试不通过的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Oshank_kumar:

got != tt.result

将其替换为类似这样的函数调用:

func EqualFloat(a, b, precision float64) bool {
	diff := a - b
	if diff < 0.0 {
		diff = -diff
	}
	return diff < precision
}

问题在于浮点数比较的精度问题。虽然测试输出显示的值看起来相同,但实际计算中存在微小的浮点误差,导致 != 比较失败。

在Go语言中,浮点数不应该直接使用 ==!= 进行比较,而应该使用误差容忍度进行比较。以下是修复后的测试代码:

package sqrt

import (
	"math"
	"testing"
)

var sqrtTests = []struct {
	num    int64
	result float64
}{
	{9, 3.0},
	{10, 3.162},
	{5, 2.236},
	{97, 9.848},
	{16, 4.0},
}

func TestSqrt(t *testing.T) {
	const epsilon = 0.001 // 设置误差容忍度
	
	for _, tt := range sqrtTests {
		got := Sqrt(tt.num)
		diff := math.Abs(got - tt.result)
		
		if diff > epsilon {
			t.Errorf("got: Sqrt(%d)=%f, want: Sqrt(%d)=%f, diff=%f", 
				tt.num, got, tt.num, tt.result, diff)
		}
	}
}

另外,你的 Sqrt 函数实现也有精度问题。这里是一个改进版本:

func Sqrt(num int64) float64 {
	const precision = 0.001

	// 整数部分
	i := int64(1)
	for ; i*i <= num; i++ {
	}
	result := float64(i - 1)

	// 小数部分
	for ; result*result <= float64(num); result += precision {
	}
	
	// 返回时减去最后一次的增量
	return result - precision
}

测试失败的具体原因是:虽然输出看起来是 3.162000,但实际计算值可能是 3.162000000000001 或类似的微小差异,导致直接相等比较失败。使用误差容忍度比较可以正确处理这种情况。

回到顶部