2011-11-16 10 views
5

in F #, ho un record con pochi campi:In FsCheck, come generare un record di test con campi non negativi?

type myRecord = { a:float; b:float; c:float } 

Sto usando FsCheck per testare alcune proprietà che utilizzano questo record. Per (a artificiosa) esempio,

let verify_this_property (r:myRecord) = myFunction(r) = (r.a * r.b)/r.c 

causa delle restrizioni di attuazione interna di myFunction, desidero avere FsCheck creare casi di test in cui ciascuno dei campi a, b, c sono limitate a non -leggianti galleggianti.

Sospetto che sia necessario creare un generatore per myRecord, ma non sono riuscito a trovare alcun esempio su come eseguire questa operazione.

Qualcuno può fornire indicazioni?

+0

Avete cura leggi [questa pagina Wiki FsCheck] (http://fscheck.codeplex.com/wikipage?title=Test%20Data%20Generators&referringTitle=Home)? Ha un esempio di come scrivere e registrare un generatore. – fmr

+2

@ fmr - Sì, ho letto attentamente tutte le pagine di Wiki FsCheck. Mentre vengono forniti i passaggi per scrivere un semplice generatore (non molto chiaramente IMHO), non sono in grado di determinare come estenderlo per creare un generatore per i record - da qui la domanda SO. –

risposta

7

Prova questo:

type Generators = 
    static member arbMyRecord = 
     fun (a,b,c) -> { myRecord.a = a; b = b; c = c } 
     <!> (Arb.generate<float> |> Gen.suchThat ((<) 0.) |> Gen.three) 
     |> Arb.fromGen 

Arb.register<Generators>() |> ignore 
Check.Quick verify_this_property 

Il <!> è un infisso map, utile per lo stile applicativa. Questo è un generatore equivalente:

Se non si desidera globalmente registrare il generatore, è possibile utilizzare forAll:

Check.Quick (forAll Generators.arbMyRecord verify_this_property) 

restringimento lasciato come esercizio;)

+0

Qual è il significato del costrutto ""? Non l'ho mai visto prima. –

+2

@DavidH: è una 'mappa' infissa, utile per lo stile applicativo. Vedi http://bugsquash.blogspot.com/2010/12/zipping-with-applicative-functors-in-f.html –

+0

@DavidH: ha spiegato un po 'di più. –

3

È possibile evitare di creare generatore personalizzato utilizzando FsCheck conditional properties

let verify_this_property (r:myRecord) = 
    (r.a > 0.0 && r.b > 0.0 && r.c > 0.0) ==> lazy (myFunction r = (r.a * r.b) * r.c) 

Anche se questo comporterà (sostanzialmente?) Lenta esecuzione del test, in quanto FsCheck dovrà scartare tutte le voci di prova idonei.