2017-08-15 3 views
7

J'essaye d'obtenir le comportement suivant avec FsCheck: Je voudrais créer un générateur qui va générer une instance de type MyUnion, avec chaque champ de chaîne étant non -null/vide.Force FsCheck pour générer NonEmptyString pour discriminer les champs union de type chaîne

type MyNestedUnion = 
    | X of string 
    | Y of int * string 

type MyUnion = 
    | A of int * int * string * string 
    | B of MyNestedUnion 

Mon type « réel » est beaucoup plus grand/plus profond que la MyUnion et FsCheck est en mesure de générer une instance sans aucun problème, mais les champs de chaîne des cas syndicaux sont parfois vides. (Par exemple, il peut générer B (Y (123, "")))

Peut-être existe-t-il une façon évidente de combiner NonEmptyString de FsCheck et son support pour générer des types d'union arbitraires qui me manquent?

Tous les conseils/pointeurs dans la bonne direction grandement appréciés.

Merci!

Répondre

5

Cela va à l'encontre du grain de tests basés sur la propriété (en ce que vous empêchez explicitement les cas de test valides d'être générées), mais vous pouvez câbler le générateur de chaîne non vide à utiliser pour toutes les chaînes:

type Alt = 
    static member NonEmptyString() : Arbitrary<string> = 
     Arb.Default.NonEmptyString() 
     |> Arb.convert 
      (fun (nes : NonEmptyString) -> nes.Get) 
      NonEmptyString.NonEmptyString 

Arb.register<Alt>() 

let g = Arb.generate<MyUnion> 

Gen.sample 1 10 g 

Notez que vous devrez réenregistrer le générateur par défaut après le test car les mappages sont globaux. Une solution plus conventionnelle consisterait à utiliser le générateur dérivé par défaut, puis à filtrer les valeurs contenant des chaînes non valides (c'est-à-dire utiliser ==>), mais cela pourrait ne pas être possible pour les types imbriqués particulièrement profonds.