在 KotlinTest 中,应该和应该之间有什么区别?



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

val expect = 0.1
val actual: Double = getSomeDoubleValue() 
actual shouldBe expect

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

[WARN]当比较双精度时考虑使用公差,例如:a应该是b +或- c

在本例中,我不想使用plusOrMinus。因此,我将代码固定为

val expect = 0.1
val actual: Double = getSomeDoubleValue() 
actual shouldBe exactly(expect)

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

根据当前来源:

infix fun Double.shouldBe(other: Double): Unit = ToleranceMatcher(other, 0.0).test(this)

其中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)
}

因此,匹配d shouldBe e将精确地比较双精度值,没有任何偏差(a - b永远不会为不同的双精度值提供0),并打印警告:

[WARN]当比较双精度时考虑使用公差,例如:a应该是b +或- 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")
    }
}

所以它会做同样的,但没有任何警告。


我猜,这个警告的含义是鼓励开发人员显式地指定精确比较双精度,或者指定容差,因为即使以不同顺序执行相同的算术运算,也可能对双精度产生不同的结果。

比较浮点数,特别是经过计算的浮点数,总是会产生舍入误差,因为某些浮点数在转换为二进制时可能无法表示。因此,在测试时,您通常必须为您认为可接受的舍入误差提供一个值。

在KotlinTest中,这是使用plusOrMinus说明符指定的。

如果在某些情况下,你知道数字应该是一个给定的值(例如,它被初始化为0或10或其他),那么使用exactly说明符。据推测,这在幕后做了一些事情来指定一个非常小的错误值,或者以其他方式比较双精度。

要断言一个双精度对象与另一个双精度对象完全相等,使用d应该是exactly(e)
要断言双精度对象在某个容差范围内相等,使用d shouldBe (e plus or - y)

来源

如果你只是自己使用shouldBe,那么系统将只做一个简单的if a == b类型测试,这将使你的测试暴露于上述舍入误差

相关内容

  • 没有找到相关文章

最新更新