5

FsCheck を使用して F# でいくつかのプロパティ テストを行っています。したがって、入力引数に関係なく、特定の条件が常に成立することを保証したいと思います。

値に対して自明な恒等関数を定義するとしfloatます。

let floatId (x : float) = x

次に、常に保持する必要があるとわかっているこの関数のテストを定義します。

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

これは簡単なテストです。float ID 関数を呼び出すと、入力された float と同じ値が返されることを確認しているだけです。

次に、この関数を FsCheck にプラグインします。

Check.Quick ``floatId returns input float``

残念ながら、このプロパティ テストは失敗します。

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

もちろん、振り返ってみると、これが起こることは明らかでしたnan <> nan

F# の構造的な比較により、これは、コレクションを含む (わずかに) より複雑なテスト ケースでも問題になる可能性があります。

float リストに対して同様の関数を設計すると、次のようになります。

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]

また同じ問題!


明らかに、独自の等値テスト関数を作成することでこの問題を回避できます。これは値には問題ありませんが、カスタム等値関数で使用を開始し、一般にコードを個々のコレクション型に特化する必要がfloatあるため、コレクションに拡張するのはより複雑になります。 .listList.forall2

F# でこの問題を解決する一般的な方法はありますか?

4

1 に答える 1

5

関数を使用してこの問題を解決できLanguagePrimitives.GenericEqualityERます。これは、等価関係セマンティクスを使用して等価性をチェックします。この関数は、リストを比較する具体的な例を実際に[nan]示しています。

テスト ケースは次のように定義できます。

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

今回:

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

(上記のプロパティが FSharp Software Foundation の Slack チャネルで提起され、このソリューションを記録に残しておくと役立つと考えたため、この質問をして回答しています。この機能については、ドキュメントを超えてオンラインでほとんど言及されていません。LanguagePrimitivesモジュール上)。

于 2016-09-06T11:19:11.940 に答える