問題タブ [fscheck]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
unit-testing - カード ゲームのディール関数でプロパティ ベースのテストを実行するにはどうすればよいですか?
私はプロパティ ベースのテストを研究しており、このタイプのテストをブラックジャック ゲームのディール関数にどのように適用できるか興味があります。
これが単体テストです(別名:サンプルベースのテスト):
プロパティベースのテストの例は何ですか?
2 枚のカードが 4 スーツの範囲内にあることをテストしますか? (つまり、スペード、ダイアモンド、ハート、クラブ) 静的型に依存することで、既にそれが保証されているのではないでしょうか?
2 枚のカードが数字または面の範囲内にあることをテストしますか? (つまり、2..10;Jack;Queen;King;Ace) 繰り返しますが、静的型に依存することで、すでにそれが保証されているのではないでしょうか?
繰り返しますが、ブラックジャック ゲームのプロパティ ベースのテストを実行する場合、何を考慮する必要がありますか?
.net - ランダムに生成された入力が役に立たない場合、プロパティ ベースのテストを再試行するにはどうすればよいですか?
私は単体テストには不慣れです。Nuget からインストールFsCheck.Nunit
しNUnitTestAdapter
て、プロパティ ベースのテストを行おうとしています。これは、計り知れない Scott Wlaschinに大きく影響されています。
属性を使用してい[<Property>]
ますが、テストの要件を満たさない入力を「スキップ」する機能が必要です。
これを行う最も簡単な方法は何ですか?
存在する場合は FsCheck/NUnit の回答を希望しますが、Visual Studio でテストを実行できる他のフレームワークも検討します。(これを正確に行うための単純な関数があるフレームワークを見たと思いましたが、それが何であるかわかりません。)
FsCheck.NUnit は、F# 型 (判別共用体など) のランダムな入力を追加作業なしで生成できるため、これまでのところ好んで使用しています。
mocking - xUnit と FsCheck を IoC で使用し、F# でモックする方法
プロパティベースのテスト手法を使用して、単体テスト F# を作成したいと考えています。しかし、私はいくつかの障害に遭遇しました。
- テストしたいコードは C# です
- ドメイン オブジェクトは EF から取得されます。つまり、コンストラクターはなく、変更可能なプロパティのみです。
- sut は、多くのコンストラクター インジェクションを必要とするクラスです。新しい機能を追加すると、その数は頻繁に変わります。コンストラクターに新しいパラメーターを追加するときに、古いテストを変更したくありません。
- sut は既に存在し、機能しているため、コンストラクターでファクトリ パラメーターを 1 つだけ受け取るようにパターンを変更すると、テストによる損傷と見なされるため、使用できません。
- FsCheck はすぐに使用できるエンティティ フレームワーク オブジェクトを生成できないため、エンティティごとに大規模なジェネレータを作成する必要があります。それを実行したり、このタスクをより簡単にするライブラリはありますか?
言い換えれば、FsCheck と Ninject (アプリケーションで使用するため、新しいものを追加することもできません) を自動エンティティ ジェネレーターおよびモック ツールと組み合わせることは可能ですか?
quickcheck - プロパティ ベースのテスト ツールを使用してイベント/コマンドを生成しますか?
私が理解しているように、ほとんどのプロパティ テスト ツールは関数のレベルで動作します。一連の引数が与えられると、そのようなツールはランダムな入力を生成し、何らかの不変条件に対して出力をテストします。
ステートフル システムをテストするためのイベントの生成が ScalaCheck に組み込まれ始めていることを読みました。しかし、私はそれに関する多くの情報を見つけることができません。これは他の *check エコシステム (fscheck、quickcheck、その他のバリエーション) でも人気が高まっていますか?
f# - FsCheck を使用して複雑なオブジェクトを生成中に、一貫性のない IEnumerable ArgumentException が発生する
問題
F# では、FsCheck を使用してオブジェクトを生成しています (Xunit テストで使用していますが、Xunit の外部で完全に再作成できるため、Xunit のことは忘れてもかまいません)。FSI で世代を 20 回実行すると、
- 50% の確率で、生成は正常に実行されます。
25% の確率で、世代は次をスローします。
/li>25% の確率で、世代は次をスローします。
/li>
状況
オブジェクトは次のとおりです。
オブジェクトが有効であるためには、次の規則に従う必要があります。
- すべての InitEvent は、すべての RefEvent の前に来る必要があります
- すべての InitEvents 文字列は一意である必要があります
- すべての RefEvent 名には、以前の対応する InitEvent が必要です
- ただし、一部の InitEvents に後で対応する RefEvents がない場合は問題ありません
- ただし、複数の RefEvents が同じ名前であっても問題ありません
実用的な回避策
有効なオブジェクトを返す関数をジェネレーターに呼び出して Gen.constant (関数) を実行させた場合、例外に遭遇することはありませんが、これは FsCheck の実行方法ではありません! :)
壊れた正しい道?
定数を生成することから完全に逃れることはできないようです (名前のリストを InitEvent の外部に格納して、RefEvent 生成がそれらを取得できるようにする必要がありますが、FsCheck ジェネレーターがどのように機能するように見えるかについては、より多くを得ることができます。
すでに確認したこと
- 申し訳ありませんが、元の質問でDebug in Interactiveを試みたことに言及するのを忘れていました。動作に一貫性がないため、追跡するのはやや困難です。ただし、例外が発生した場合、ジェネレーター コードの最後と生成されたサンプルを要求しているものの間にあるようです。FsCheck が生成を実行している間、不正なシーケンスを処理しようとしているようです。さらに、これはジェネレーターのコーディングが間違っているためだと思います。
- FsCheck を使用した IndexOutOfRangeExceptionは、同様の状況の可能性を示唆しています。上記の単純化が基づいている実際のテストで、 Resharper テスト ランナーとXunit のコンソール テスト ランナーの両方を介して Xunit テストを実行しようとしました。どちらのランナーも同じ動作を示すため、問題は別の場所にあります。
- FsCheckでは、負でないフィールドを含むテスト レコードを生成する方法は? FsCheck で「複雑な」オブジェクトを生成するにはどうすればよいですか? 複雑さの少ないオブジェクトの作成を扱います。最初のものは私が持っているコードにたどり着くのに非常に役立ちました.生成された名前。それはすべてそれに戻っているようです-ランダムな名前を作成する必要があり、それから引き出されて InitEvents の完全なセットを作成し、RefEvents のいくつかのシーケンスを作成します。どちらも「定数」リストを参照しますが、そうではありません。私がまだ出会ったことのないものと一致します。
- FsCheck に含まれている例を含め、見つけることができる FsCheck ジェネレーターのほとんどの例を調べました : https://github.com/fscheck/FsCheck/blob/master/examples/FsCheck.Examples/Examples.fs内部の一貫性を必要とするオブジェクトを扱い、全体的には役に立ちましたが、このケースには当てはまらないようです。
- おそらくこれは、役に立たない観点からオブジェクトの生成に取り組んでいることを意味します。上記のルールに従うオブジェクトを生成する別の方法がある場合は、それに切り替えることにオープンです。
- 問題からさらに後退して、「オブジェクトにそのような制限がある場合、無効なオブジェクトを受け取るとどうなりますか?おそらく、無効なオブジェクトをより適切に処理するために、このオブジェクトが消費される方法を再考する必要があります。」ケース。」たとえば、RefEvent でこれまで見たことのない名前をオンザフライで初期化できた場合、最初に InitEvent を指定する必要はなくなります。名前。私はこの種の解決策を受け入れますが、少しやり直す必要があります-長期的には、それだけの価値があるかもしれません. それまでの間、FsCheck を使用して上記の規則に従う複雑なオブジェクトを確実に生成するにはどうすればよいかという疑問が残ります。
ありがとう!
EDIT(S): 解決の試み
Mark Seemann's answer のコードは機能しますが、私が探していたものとはわずかに異なるオブジェクトが生成されます (オブジェクト ルールが明確ではありませんでしたが、明確になったことを願っています)。彼の作業コードを私のジェネレーターに入れます:
これにより、すべての InitEvent に一致する RefEvent があり、各 InitEvent に対して RefEvent が 1 つだけ存在するオブジェクトが生成されます。名前ごとに複数の RefEvent を取得できるようにコードを微調整しようとしていますが、すべての名前に RefEvent が必要なわけではありません。例: Init foo、Init bar、Ref foo、Ref foo は完全に有効です。これを微調整しようとしています:
変更されたコードは、一貫性のない動作を示します。興味深いことに、20 回のサンプル実行のうち、3 回しか機能しませんでしたが (10 回から減少)、不十分な数の要素が 8 回スローされ、The input must be non-negativeが 9 回スローされました。これらの変更により、エッジ ケースが当たる確率が2倍。これで、エラーのあるコードの非常に小さなセクションに到達しました。
マークは、変更された要件に対応するために、別のバージョンで迅速に対応しました。
これにより、一部の名前で RefEvent を持たないようにすることができました。
最終コード 重複する RefEvents が発生するように、非常にマイナーな調整を行います。
マーク・シーマンに感謝!