我使用 FsCheck 进行基于属性的测试,因此我为自定义类型定义了一组生成器。一些类型由其他类型组成,并且所有类型都有生成器。为字母数字类型定义了一个生成器后,我想为 RelativeUrl 类型定义一个生成器,RelativeUrl 是由斜线符号分隔的 1-9 个字母数字值的列表。这是有效的定义(Alpanumeric 具有将其转换为字符串的“Value”属性):
static member RelativeUrl() =
Gen.listOfLength (System.Random().Next(1, 10)) <| Generators.Alphanumeric()
|> Gen.map (fun list -> String.Join("/", list |> List.map (fun x -> x.Value)) |> RelativeUrl)
尽管它很简单,但我不喜欢使用 Random.Next 方法而不是使用 FsCheck 随机生成器。所以我试着像这样重新定义它:
static member RelativeUrl_1() =
Arb.generate<byte>
|> Gen.map int
|> Gen.suchThat (fun x -> x > 0 && x <= 10)
|> Gen.map (fun length -> Gen.listOfLength length <| Generators.Alphanumeric())
|> Gen.map (fun list -> String.Join("/", list))
编译器接受它,但实际上它是错误的:最后一条语句中的“列表”不是字母数字值的列表,而是 Gen。下一次尝试:
static member RelativeUrl() =
Arb.generate<byte>
|> Gen.map int
|> Gen.suchThat (fun x -> x > 0 && x <= 10)
|> Gen.map (fun length -> Gen.listOfLength length <| Generators.Alphanumeric())
|> Gen.map (fun list -> list |> Gen.map (fun elem -> String.Join("/", elem |> List.map (fun x -> x.Value)) |> RelativeUrl))
但这也不起作用:我返回的是 RelativeUrl 的 Gen,而不是 RelativeUrl 的 Gen。那么在不同级别组合生成器的正确方法是什么?