通过从可能性池中选择 FsCheck 生成器

FsCheck Generators by Selecting From Pools of Possibilities

有没有一种方法可以在 FsCheck 中通过从每个字符串列表中只选择一个项目然后连接结果来生成一个字符串?

我完全被卡住了,似乎无法弄清楚。我看过 docs and in the github repo for something similar. And I've done most of my reading on FsCheck from FSharpForFunAndProfit

这就像我想的那样:

let rand = System.Random()
let randInt max = rand.Next(0, max)

let selectLetter (string: string) = 
    let whichLettersIndex = String.length string |> randInt
    string.Substring(whichLettersIndex, 1)

let generateOddlySpelledWord listOfStrings = 
    List.map selectLetter listOfStrings
    |> String.concat ""

let usingGenerateOddlySpelledWord =
    generateOddlySpelledWord ["zZ"; "oO0Ò"; "eEê"]

这应该会生成类似 "Z0ê" 或 "zÒE" 的内容。

这是你想要的吗?

open FsCheck

let createGenerators (l : string seq) =
    l |> Seq.map Gen.elements |> Seq.toList

type OddlySpelledWords =
    static member String() =
        ["zZ"; "oO0Ò"; "eEê"]
        |> createGenerators
        |> Gen.sequence
        |> Gen.map (List.map string >> String.concat "")
        |> Arb.fromGen

临时测试:

open FsCheck.Xunit

[<Property(Arbitrary = [| typeof<OddlySpelledWords> |])>]
let test (s : string) =
    printfn "%s" s

输出(截断):

  z0ê
  ZÒe
  ZOe
  zoê
  ZÒe
  zoê
  Z0e
  zoê
  z0ê
  ZOe
  zÒê
  z0E
  zoe

说明

createGenerators 函数的类型为 seq string -> Gen<char> list,它使用 Gen.elements 从每个字符串创建一个 Gen,因为字符串也是 char seq ]; Gen.elements 创建一个 Gen 将从每个字符串中选择这些 char 值之一。

然后它使用 Gen.sequenceGen<char> list 转换为 Gen <char list>,然后从那里映射。


顺便说一句,你也可以内联 createGenerators:

type OddlySpelledWords =
    static member String() =
        ["zZ"; "oO0Ò"; "eEê"]
        |> List.map Gen.elements
        |> Gen.sequence
        |> Gen.map (List.map string >> String.concat "")
        |> Arb.fromGen