Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between shouldBe and shouldBe exactly in KotlinTest?

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?

like image 760
mmorihiro Avatar asked Nov 15 '16 12:11

mmorihiro


1 Answers

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.

like image 168
hotkey Avatar answered Oct 10 '22 02:10

hotkey