gpt4 book ai didi

ScalaCheck 有效/无效的测试边界

转载 作者:行者123 更新时间:2023-12-03 14:40:55 25 4
gpt4 key购买 nike

我正在使用 ScalaCheck 在 ScalaTest 中进行一些基于属性的测试。假设我想测试一个函数,f(x: Double): Double仅针对 x >= 0.0 定义的, 并返回 NaN对于该域之外的参数。理想情况下,我想做这样的事情:

import org.scalatest.FunSpec
import org.scalatest.prop.GeneratorDrivenPropertyChecks

def f(x: Double) = Math.sqrt(x) // The actual function isn't important.

class FTest
extends FunSpec
with GeneratorDrivenPropertyChecks {
describe("f(x)") {
it("must accept every argument value and handle it correctly") {
forAll { x: Double =>
val r = f(x)
if(x >= 0.0) assert(!r.isNaN && r === Math.sqrt(x)) // Too simplistic, I know. ;-)
else assert(r.isNaN)
}
}
}
}

现在,这相当优雅并且有效,但我担心边界检查,因为我怀疑 - 在一般情况下 - ScalaCheck 是否能够找到边界并测试函数是否正确响应任一侧的值的边界(在这种情况下> = 0.0)。当然,我可以使用 whenever 将这两个条件分开。 (ScalaTest 替代了 ScalaCheck 的 ==> 操作符),但这需要更多的努力并且浪费了很多生成的值:

class FTest2
extends FunSpec
with GeneratorDrivenPropertyChecks {
describe("f(x)") {
it("must accept every valid argument value and handle it correctly") {
forAll { x: Double =>
whenever(x >= 0.0) {
val r = f(x)
assert(!r.isNaN && r === Math.sqrt(x))
}
}
}
it("must report the correct error value for invalid argument values") {
forAll { x: Double =>
whenever(x < 0.0) assert(f(x).isNaN)
}
}
}
}

(我知道我也可以使用客户生成器来限制范围,这样就不需要 whenever,但我认为这不是重点。如果我错了,请随时纠正我。)

所以,我很好奇的是:
  • 有没有办法向 ScalaCheck 提示边界值是什么,并确保它选择该值及其两侧的值?
  • 是否有任何替代方案同样优雅,但在自动查找边界方面做得更好?

  • 谢谢你的帮助~

    最佳答案

    ScalaCheck 无法自动确定您的函数将哪些值视为有效;您需要在您的属性中(使用类似 whenever )或在您的生成器中对此信息进行编码。选择哪种方法是特定于上下文的。

    保持属性“小”是可取的:集中的​​、正交的属性更容易读/写/维护,并且您可以随时组合它们以构建更全面的属性。因此,我会将这两个属性(开心和不开心的情况)分开。

    为了避免“浪费”生成的值,我将使用两个单独的生成器(一个用于非负 double ,另一个用于负 double );不需要 whenever用这种方法。

    val genNonnegativeDouble: Gen[Double] = Gen.choose(0, Double.MaxValue)

    val genNegativeDouble: Gen[Double] = Gen.negNum[Double]

    您的属性将如下所示:
    final class FTest2
    extends FunSpec
    with GeneratorDrivenPropertyChecks {

    describe("f") {
    it("must accept every valid argument value and handle it correctly") {
    forAll(genNonnegativeDouble) { x =>
    val r = f(x)
    assert(!r.isNaN && r === Math.sqrt(x))
    }
    }

    it("must report the correct error value for invalid argument values") {
    forAll(negativeDouble) { x =>
    assert(f(x).isNaN)
    }
    }
    }

    }

    顺便,
  • 您可能应该返回 Double.NaN 以外的其他内容表示失败; Option[Double]在这里是一个很好的候选人,因为失败的原因只有一个。
  • 您应该只检查 double 是否近似相等。
  • 关于ScalaCheck 有效/无效的测试边界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42017693/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com