在 KotlinTest 中 shouldBe 和 shouldBe 之间有什么区别?

mmo*_*iro 5 kotlin kotlintest

这是使用 KotlinTest 1.3.5 的测试代码。

val expect = 0.1
val actual: Double = getSomeDoubleValue() 
actual shouldBe expect
Run Code Online (Sandbox Code Playgroud)

并且在运行代码时打印了此警告。

[警告] 比较双打时考虑使用容差,例如:a shouldBe b plusOrMinus c

在这种情况下,我不想使用plusOrMinus. 所以,我将代码固定为

val expect = 0.1
val actual: Double = getSomeDoubleValue() 
actual shouldBe exactly(expect)
Run Code Online (Sandbox Code Playgroud)

现在,没有警告。
不过,我想知道的区别shouldBeshouldBe exactly。它是什么?

hot*_*key 5

根据目前的消息来源

infix fun Double.shouldBe(other: Double): Unit = ToleranceMatcher(other, 0.0).test(this)
Run Code Online (Sandbox Code Playgroud)

这里ToleranceMatcher

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)
}
Run Code Online (Sandbox Code Playgroud)

因此,匹配d shouldBe e将在没有任何容差的情况下完全比较双打(a - b永远不会0为不同的双打提供)并打印警告:

[警告] 比较双打时考虑使用容差,例如:a shouldBe b plusOrMinus c

exactly(d) 定义为

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")
    }
}
Run Code Online (Sandbox Code Playgroud)

这样它就会做同样的事情,尽管没有任何警告。


我想,这个警告的意思是鼓励开发人员明确指定精确比较双精度,或者指定容差,因为即使以不同顺序执行的相同算术也可能会产生不同的双精度结果。

  • 实际上警告有点误导,它必须是`a shouldBe (b plusOrMinus c)`。见 https://github.com/kotlintest/kotlintest/issues/259 (2认同)