From documentation:
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
And their code seems to be identical in purpose:
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
}
What is the difference? what are the use cases where one would be used over the other and vice versa?
They are related but not identical.
InDelta
receives an absolute value and checks that the difference is less than that value.
InEpsilon
receives a % of difference that would be acceptable.
The behaviour of InDelta
is quite straightforward:
InDelta(t, 100, 101, 2) // that's OK
InDelta(t, 100, 103, 2) // fail!
But sometimes, you just care that the actual value is not too far away from the expected value.
Depending on how small or large the expected value is "not too far away" might get tricky with InDelta
.
It might be a problem to use the same delta
value for any number:
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...
If you use InEpsilon
, you can always use the same %:
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
In summary, the use case for ÌnEpsilon
is to discard small differences (and making "small" relative to the actual values compared).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With