This is a test code using KotlinTest 1.3.5.
val expect = 0.1
val actual: Double = getSomeDoubleValue()
actual shouldBe expect
and this warning was printed when the code was run.
[WARN] When comparing doubles consider using tolerance, eg: a shouldBe b plusOrMinus c
In this case, I didn't want to use plusOrMinus
.
So, I fixed the code to
val expect = 0.1
val actual: Double = getSomeDoubleValue()
actual shouldBe exactly(expect)
Now, there is no warning.
However, I'd like to know the difference between shouldBe
and shouldBe exactly
. What is it?
According to the current sources:
infix fun Double.shouldBe(other: Double): Unit = ToleranceMatcher(other, 0.0).test(this)
where ToleranceMatcher
is
class ToleranceMatcher(val expected: Double, val tolerance: Double) : Matcher<Double> {
override fun test(value: Double) {
if (tolerance == 0.0)
println("[WARN] When comparing doubles consider using tolerance, eg: a shouldBe b plusOrMinus c")
val diff = Math.abs(value - expected)
if (diff > tolerance)
throw AssertionError("$value is not equal to $expected")
}
infix fun plusOrMinus(tolerance: Double): ToleranceMatcher = ToleranceMatcher(expected, tolerance)
}
So, matching d shouldBe e
will compare the doubles exactly without any tolerance (a - b
will never give 0
for different doubles) and print the warning:
[WARN] When comparing doubles consider using tolerance, eg: a shouldBe b plusOrMinus c
Whereas exactly(d)
is defined as
fun exactly(d: Double): Matcher<Double> = object : Matcher<Double> {
override fun test(value: Double) {
if (value != d)
throw AssertionError("$value is not equal to expected value $d")
}
}
So that it will do the same, though without any warning.
I guess, the meaning of this warning is to encourage developers to specify it explicitly that doubles are compared exactly, or else specify the tolerance, because even the same arithmetics done in different order might produce different results with doubles.
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