2016-09-06 3 views
5

Ich mache einige Eigenschaftstests in F # mit FsCheck. Ich möchte daher garantieren, dass bestimmte Bedingungen unabhängig von Eingabeargumenten immer gelten.Was ist eine kurze, allgemeine Methode zum Testen von Eigenschaften gegen Nanowerte in F #?

Betrachte ich definieren eine triviale Identitätsfunktion für float Werte.

let floatId (x : float) = x 

ich einen Test dieser Funktion dann definieren, die ich weiß, immer halten sollte:

ist
let ``floatId returns input float`` x = floatId x = x 

Diese triviale Test, bin Überprüfung ich nur, dass meine Schwimmer Identität Funktion aufrufen, wie die das gleiche zurück Eingabe float.

steck ich dann diese Funktion in FsCheck:

Check.Quick ``floatId returns input float`` 

Leider versagt diese Eigenschaft Test!

Falsifiable, after 21 tests (0 shrinks) (StdGen (1872424299,296201373)): 
Original: 
nan 

Natürlich, im Rückblick, es ist ziemlich offensichtlich war dies passieren würde, wissen wir, dass nan <> nan.

Aufgrund struktureller Vergleiche in F # kann dies (etwas) komplexere Testfälle mit Sammlungen erschweren.

Wenn ich entwerfe eine ähnliche Funktion für Schwimmer Listen:

let listFloatId (lst : float list) = lst 

let ``listFloatId returns input float list`` lst = listFloatId lst = lst 
Falsifiable, after 6 tests (3 shrinks) (StdGen (1874889363,296201373)): 
Original: 
[nan; 2.0; 2.25; 4.940656458e-324] 
Shrunk: 
[nan] 

Das gleiche Problem wieder!


Natürlich kann ich um dieses Problem Ingenieur durch meine eigenen Gleichheit Testfunktionen zu schaffen, das ist in Ordnung für float Werte, aber es wird immer komplexer, um Sammlungen wie list zu erweitern, da ich mit meiner benutzerdefinierten Gleichheit Funktion List.forall2 anfangen und generell meinen Code für jeden einzelnen Sammlungstyp zu spezialisieren.

Gibt es eine allgemeine Möglichkeit, dieses Problem in F # zu lösen?

+1

Ich würde das wahrscheinlich mit einem neuen Operator lösen, der eine Gleichheit berücksichtigte, nan –

+0

@JohnPalmer Ich tue dies, um eine mögliche Lösung zu setzen, die in der Aufzeichnung nicht gut bekannt zu sein scheint. Würde mich definitiv interessieren, andere zu hören. – TheInnerLight

+0

Ah - ich wusste nicht, dass du schon eine Antwort dafür hast - es sieht so aus, als ob diese Funktion im Grunde das ist, was du brauchst. –

Antwort

5

Sie können dieses Problem mit der Funktion LanguagePrimitives.GenericEqualityER lösen. Dies überprüft die Gleichheit unter Verwendung der Äquivalenzrelations-Semantik. Diese Funktion zeigt das spezifische Beispiel für den Vergleich von Listen.

let ``ER : floatId returns input float`` x = LanguagePrimitives.GenericEqualityER (floatId x) x 

let ``ER : listFloatId returns input float list`` lst = LanguagePrimitives.GenericEqualityER (listFloatId lst) lst 

Diesmal:

Ok, passed 100 tests. 
Ok, passed 100 tests. 

(Ich frage, und die Beantwortung dieser Frage, weil die obige Eigenschaft wurde in angehoben

Testfälle können wie folgt definiert werden der FSharp Software Foundation Slack-Kanal und ich dachte, es wäre nützlich, diese Lösung zu Protokoll zu haben.Ich kann fast keine Erwähnung dieser Funktion online neben der Dokumentation auf dem LanguagePrimitives Modul finden).

Verwandte Themen