我想测试一个属性,其中我使用2个概率率p1和p2,它们必须满足0< p1< p2< 1
let arraySizeCheck (p1:float, p2:float, xs:list<int>) =
(p1 < p2 && p1 > 0.0 && p1 < 1.0 && p2 > 0.0 && p2 < 1.0 && Seq.length xs > 0) ==>
(lazy
(
let bf1 = BloomFilter(p1, xs)
let bf2 = BloomFilter(p2, xs)
bf2.BitArraySize < bf1.BitArraySize
)
)
Check.Quick arraySizeCheck
我试过上面的例子,但测试结果似乎是
0次测试后参数耗尽。 val it:unit =()
此外,我更喜欢列表xs不包含重复项。任何帮助写这个属性的测试将不胜感激。感谢。
答案 0 :(得分:2)
更惯用的方法是使用gen
模块中的Gen
计算表达式和组合函数。不幸的是,返回生成随机浮点数的生成器的函数被隐藏(参见source code。)
但我们可以创建自己的:
open System
open FsCheck
open FsCheck.Gen
open FsCheck.Prop
/// Generates a random float [0..1.0]
let rand = Gen.choose (0, Int32.MaxValue) |> Gen.map (fun x -> double x / (double Int32.MaxValue))
/// Generates a random float in the given range (inclusive at both sides)
let randRange a b = rand |> Gen.map (fun x -> a + (b - a) * x)
let arraySizeCheck =
Prop.forAll
(Arb.fromGen <| gen {
// generate p1 and p2 such that 0 <= p1 <= p2 <= 1
let! p1 = randRange 0.0 1.0
let! p2 = randRange p1 1.0
// generate non-empty Seq<int>
let! xs = Gen.nonEmptyListOf Arb.generate<int> |> Gen.map Seq.ofList
return BloomFilter(p1, xs), BloomFilter(p2, xs)
})
(fun (bf1, bf2) -> bf2.BitArraySize < bf1.BitArraySize)
Check.Quick arraySizeCheck
请注意,此处p1
和p2
生成0 <= p1 <= p2 <= 1
,这不是您所需要的。但我认为对rand
函数的简单修改可以解决这个问题。