InDelta 和 InEpsilon 之间的区别
Difference between InDelta and InEpsilon
来自文档:
https://godoc.org/github.com/stretchr/testify/assert#InDelta
InDelta asserts that the two numerals are within delta of each other
https://godoc.org/github.com/stretchr/testify/assert#InEpsilon
InEpsilon asserts that expected and actual have a relative error less than epsilon
而且他们的代码似乎在目的上是相同的:
func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
af, aok := toFloat(expected)
bf, bok := toFloat(actual)
if !aok || !bok {
return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...)
}
if math.IsNaN(af) {
return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...)
}
if math.IsNaN(bf) {
return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...)
}
dt := af - bf
if dt < -delta || dt > delta {
return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
}
return true
}
func calcRelativeError(expected, actual interface{}) (float64, error) {
af, aok := toFloat(expected)
if !aok {
return 0, fmt.Errorf("expected value %q cannot be converted to float", expected)
}
if af == 0 {
return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
}
bf, bok := toFloat(actual)
if !bok {
return 0, fmt.Errorf("actual value %q cannot be converted to float", actual)
}
return math.Abs(af-bf) / math.Abs(af), nil
}
// InEpsilon asserts that expected and actual have a relative error less than epsilon
//
// Returns whether the assertion was successful (true) or not (false).
func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
actualEpsilon, err := calcRelativeError(expected, actual)
if err != nil {
return Fail(t, err.Error(), msgAndArgs...)
}
if actualEpsilon > epsilon {
return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
" < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...)
}
return true
}
有什么区别?在哪些用例中,一个可以替代另一个,反之亦然?
它们相关但不相同。
InDelta
接收一个绝对值并检查差值是否小于该值。
InEpsilon
收到可接受的差异百分比。
InDelta
的行为非常简单:
InDelta(t, 100, 101, 2) // that's OK
InDelta(t, 100, 103, 2) // fail!
但有时候,你只是关心实际值与期望值相差不是太远。
取决于预期值的大小 "not too far away" 可能会变得棘手 InDelta
。
对任何数字使用相同的 delta
值可能会出现问题:
InDelta(t, 100, 101, 2) // ok, 101 is "not too far away" from 100
InDelta(t, 1, 2, 2) // hm, 2 sounds "too far away" from 1...
如果您使用 InEpsilon
,您始终可以使用相同的 %:
InEpsilon(t, 100, 101, 0.02) // ok, up to 102 would be acceptable
InEpsilon(t, 1, 2, 0.02) // will not pass.. this time up to 1.02 would be acceptable
总而言之,ÌnEpsilon
的用例是丢弃小差异(并使 "small" 相对于实际值进行比较)。
来自文档:
https://godoc.org/github.com/stretchr/testify/assert#InDelta
InDelta asserts that the two numerals are within delta of each other
https://godoc.org/github.com/stretchr/testify/assert#InEpsilon
InEpsilon asserts that expected and actual have a relative error less than epsilon
而且他们的代码似乎在目的上是相同的:
func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
af, aok := toFloat(expected)
bf, bok := toFloat(actual)
if !aok || !bok {
return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...)
}
if math.IsNaN(af) {
return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...)
}
if math.IsNaN(bf) {
return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...)
}
dt := af - bf
if dt < -delta || dt > delta {
return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
}
return true
}
func calcRelativeError(expected, actual interface{}) (float64, error) {
af, aok := toFloat(expected)
if !aok {
return 0, fmt.Errorf("expected value %q cannot be converted to float", expected)
}
if af == 0 {
return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
}
bf, bok := toFloat(actual)
if !bok {
return 0, fmt.Errorf("actual value %q cannot be converted to float", actual)
}
return math.Abs(af-bf) / math.Abs(af), nil
}
// InEpsilon asserts that expected and actual have a relative error less than epsilon
//
// Returns whether the assertion was successful (true) or not (false).
func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
actualEpsilon, err := calcRelativeError(expected, actual)
if err != nil {
return Fail(t, err.Error(), msgAndArgs...)
}
if actualEpsilon > epsilon {
return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
" < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...)
}
return true
}
有什么区别?在哪些用例中,一个可以替代另一个,反之亦然?
它们相关但不相同。
InDelta
接收一个绝对值并检查差值是否小于该值。
InEpsilon
收到可接受的差异百分比。
InDelta
的行为非常简单:
InDelta(t, 100, 101, 2) // that's OK
InDelta(t, 100, 103, 2) // fail!
但有时候,你只是关心实际值与期望值相差不是太远。
取决于预期值的大小 "not too far away" 可能会变得棘手 InDelta
。
对任何数字使用相同的 delta
值可能会出现问题:
InDelta(t, 100, 101, 2) // ok, 101 is "not too far away" from 100
InDelta(t, 1, 2, 2) // hm, 2 sounds "too far away" from 1...
如果您使用 InEpsilon
,您始终可以使用相同的 %:
InEpsilon(t, 100, 101, 0.02) // ok, up to 102 would be acceptable
InEpsilon(t, 1, 2, 0.02) // will not pass.. this time up to 1.02 would be acceptable
总而言之,ÌnEpsilon
的用例是丢弃小差异(并使 "small" 相对于实际值进行比较)。