I have a bunch of types with strings all over the place. I want to write property tests for functions operating on these types, using FsCheck. For all of them, I know that I will never get strings that are null or are non alpha-numeric. Ergo I want to restrict value generation for strings accordingly.
I tried this:
let charSet= "abc" // simplified for the example
let isValidString (s:string) = null<>s && not (s |> Seq.exists (fun c -> not (charSet |> Seq.contains c)))
let createConfig left right = {LeftLanguageName= left; RightLanguageName= right}
let generateString= Arb.generate<string> |> Gen.filter isValidString
let generateConfig= createConfig <!> generateString <*> generateString
type Generators =
static member String() =
{
new Arbitrary<string>() with
override x.Generator = generateString
}
static member LanguageConfiguration()=
{
new Arbitrary<LanguageConfiguration>() with
override x.Generator = generateConfig
}
Arb.register<Generators>() |> ignore
However, FsCheck keeps generating values like this
Falsifiable, after 14 tests (9 shrinks) (StdGen (2144073619,296598634)):
Original:
{LeftLanguageName = " 1c\J
";
RightLanguageName = "\026z^k";} (At least one control character has been escaped as a char code, e.g. \023)
Shrunk:
{LeftLanguageName = "
";
RightLanguageName = "";}
So obviously I am missing something, but I got no idea what.
I looked at
How to generate null strings for FsCheck tests
and
http://blog.nikosbaxevanis.com/2015/09/25/regex-constrained-strings-with-fscheck/
but neither of them tries to override string generation globally (within scope).