gpt4 book ai didi

f# - 在实现基于属性的测试时,我什么时候应该在前置条件表达式上使用输入生成器?

转载 作者:行者123 更新时间:2023-12-04 23:17:41 24 4
gpt4 key购买 nike

在实现基于属性的测试时,我应该什么时候在前置条件表达式上使用输入生成器?

选择特定选项时是否需要考虑性能?

在内部,一种方法是否不可避免地使用另一种方法?

我认为与输入生成器相比,前置条件表达式需要更长的时间来执行。有没有人测试过这个?

为什么我们需要两者?

最佳答案

当您使用前置条件表达式(例如 FsCheck 的 ==> 运算符)时,您实际上是在丢弃数据。即使这种情况只发生在百分之一的情况下,您仍然会为普通属性丢弃 1 个输入集(因为 FsCheck 中的默认执行次数是 100)。

扔掉 100 分之一可能没什么大不了的。

但是,有时您会丢弃更多数据。例如,如果你只想要正数,你可以写一个像 x > 0 这样的前提条件。 ,但由于 FsCheck 也生成负数,因此在生成它们后,您将丢弃所有值的 50%。这可能会使您的测试运行得更慢(但与往常一样,当涉及到性能考虑时:测量)。

出于这个原因,FsCheck 带有用于正数的内置生成器,但有时,您需要对可能的输入值范围进行更细粒度的控制,如 this example .

如果做FizzBuzz kata ,例如,您可以 write your test for the FizzBuzz case like this :

[<Property(MaxFail = 2000)>]
let ``FizzBuzz.transform returns FizzBuzz`` (number : int) =
number % 15 = 0 ==> lazy
let actual = FizzBuzz.transform number
let expected = "FizzBuzz"
expected = actual

注意 MaxFail 的使用属性(property)。您需要它的原因是因为该前提条件会丢弃 15 个生成的候选中的 14 个。默认情况下,FsCheck 会在放弃之前尝试 1000 个候选,但是如果您丢弃 15 个候选中的 14 个,则平均只有 67 个与前提条件匹配的值。由于 FsCheck 的默认目标是执行一个属性 100 次,所以它放弃了。

MaxFail属性意味着,您可以调整默认值。对于 2000 个候选对象,您应该预期平均有 133 个前提条件匹配。

不过,它感觉并不是特别有效,因此您也可以使用自定义生成器:
[<Property(QuietOnSuccess = true)>]
let ``FizzBuzz.transform returns FizzBuzz`` () =
let fiveAndThrees =
Arb.generate<int> |> Gen.map ((*) (3 * 5)) |> Arb.fromGen
Prop.forAll fiveAndThrees <| fun number ->

let actual = FizzBuzz.transform number

let expected = "FizzBuzz"
expected = actual

这使用 an ad-hoc in-line Arbitrary .这更有效,因为不会丢弃任何数据。

我的倾向是使用前提条件,如果它是 only throw away the occasional unmatching input .在大多数情况下,我更喜欢自定义生成器。

关于f# - 在实现基于属性的测试时,我什么时候应该在前置条件表达式上使用输入生成器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36191290/

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