Visual Studio 2013 内で Resharper のテスト ランナーを使用して F# コードをユニット テストするために NUnit を使用しています。
type MyRecord = { A : int; B : int }
let f () = { A = 4; B = 7 }
次のようなテストケースを(FSUnitを使用して)書くと:
[<Test>] let ``test that always fails`` () = f () |> should be { A = 77; B = 99 }
「Expected: MyNamespace.MyRecord but found: MyNamespace.MyRecord」という行に沿って、非常に役に立たない出力メッセージが表示されます。
問題はもちろん、NUnit が明らかobject.ToString()
に出力メッセージを生成するために使用していることですが、sprintf "%A" object
代わりに、"Expected: { A = 77; B = 99} but found: { A = 4; B = 7}".
ToString
次のように、すべてのレコードおよび判別共用体タイプを上書きできることを知っています。
type MyRecord = { A : int; B : int } with override this.ToString () = sprintf "%A" this
ただし、これにより、テスト目的のみに必要なコードで型定義が乱雑になり、このコードをすべての型定義にコピーして貼り付けるときに、繰り返し禁止の原則に多少違反します。また、F# 3.1 では、型拡張にオーバーライド メンバーを追加することは非推奨になっていることにも注意してください。
古い質問
問題は、明示的にオーバーライドせずに失敗した NUnit テストの構造化された出力を取得する方法はありますToString
か? NUnit 用のプラグイン メカニズムはありますか? 私はNUnitのソースをチェックしましたが、それを行うための明白な方法やサポートされている方法はないようです。ソリューションは高速である必要はありません。結局のところ、コードは失敗した単体テストでのみ実行されます。ただし、これは一般的であり、コードを変更することなく、将来追加されるすべての F# レコードおよび判別共用体型で機能する必要があります。ありがとう。
新しい質問
Mark Seemann がコメントで指摘したように、Unquote ライブラリは、構造化されていない出力に問題がない代替手段です。そこで、FSUnit を Unquote に置き換えます。ただし、Unquote にはもう 1 つの問題があります。F# のリフレクション ライブラリを使用して、判別共用体を評価および削減します。どうやら、リフレクションは別のライブラリで定義された内部型を処理できないため、すべての単体テストが例外で失敗します。回避策は、すべてのタイプを公開することですが、これは明らかに理想的ではありません。
だから私のセットアップは次のとおりです。テストする必要がある内部型を含むライブラリ。そのライブラリはInternalsVisibileTo
属性を使用して、その内部をテスト アセンブリから見えるようにします。テストが実行されると、Unquote は F# のリフレクションを使用しますが、これは内部型を正しく反映できないようです。
別の既知の回避策はありますか?