15

私は特に、言語の独自の機能を利用できるフレームワークを探しています。私はFsUnitを知っています。他に何かお勧めしますか、そしてその理由は何ですか?

4

3 に答える 3

27

私自身の単体テストライブラリであるUnquoteは、F#の引用を利用して、テストアサーションを単純な静的にチェックされたF#ブール式として記述し、段階的なテスト失敗メッセージを自動的に生成できるようにします。たとえば、次の失敗したxUnitテスト

[<Fact>]
let ``demo Unquote xUnit support`` () =
    test <@ ([3; 2; 1; 0] |> List.map ((+) 1)) = [1 + 3..1 + 0] @>

次の失敗メッセージを生成します

Test 'Module.demo Unquote xUnit support' failed: 

([3; 2; 1; 0] |> List.map ((+) 1)) = [1 + 3..1 + 0]
[4; 3; 2; 1] = [4..1]
[4; 3; 2; 1] = []
false

        C:\File.fs(28,0): at Module.demo Unquote xUnit support()

FsUnitとUnquoteには同様の使命があります。それは、慣用的な方法でテストを記述できるようにすることと、有益な失敗メッセージを生成することです。しかし、FsUnitは、実際にはNUnit制約の小さなラッパーであり、構成可能な関数呼び出しの背後にオブジェクト構造を隠すDSLを作成します。ただし、コストがかかります。アサーションの静的型チェックが失われます。たとえば、次はFsUnitで有効です

[<Test>]
let test1 () =
    1 |> should not (equal "2")

ただし、Unquoteを使用すると、F#の静的型チェック機能がすべて利用できるため、同等のアサーションもコンパイルされず、テストコードにバグが発生するのを防ぐことができます。

[<Test>] //yes, Unquote supports both xUnit and NUnit automatically
let test2 () =
    test <@ 1 <> "2" @> //simple assertions may be written more concisely, e.g. 1 <>! "2"
    //           ^^^
    //Error 22 This expression was expected to have type int but here has type string

また、引用符はコンパイル時にアサーション式に関するより多くの情報を取得できるため、失敗メッセージもはるかに豊富になります。たとえば、失敗したFsUnitアサーション1 |> should not (equal 1)はメッセージを生成します

Test 'Test.Swensen.Unquote.VerifyNunitSupport.test1' failed: 
  Expected: not 1
  But was:  1
    C:\Users\Stephen\Documents\Visual Studio 2010\Projects\Unquote\VerifyNunitSupport\FsUnit.fs(11,0): at FsUnit.should[a,a](FSharpFunc`2 f, a x, Object y)
    C:\Users\Stephen\Documents\Visual Studio 2010\Projects\Unquote\VerifyNunitSupport\VerifyNunitSupport.fs(29,0): at Test.Swensen.Unquote.VerifyNunitSupport.test1()

Unquoteアサーションが失敗1 <>! 1すると、次の失敗メッセージが生成されます(よりクリーンなスタックトレースにも注意してください)

Test 'Test.Swensen.Unquote.VerifyNunitSupport.test1' failed: 

1 <> 1
false

    C:\Users\Stephen\Documents\Visual Studio 2010\Projects\Unquote\VerifyNunitSupport\VerifyNunitSupport.fs(29,0): at Test.Swensen.Unquote.VerifyNunitSupport.test1()

そしてもちろん、この回答の冒頭にある私の最初の例から、引用符で囲まれていない式と失敗メッセージがどれほど豊富で複雑であるかがわかります。

プレーンなF#式をFsUnit DSLのテストアサーションとして使用するもう1つの主な利点は、単体テストを開発するF#プロセスに非常によく適合することです。多くのF#開発者は、FSIの助けを借りてコードを開発およびテストすることから始めていると思います。したがって、アドホックFSIテストから正式なテストに移行するのは非常に簡単です。実際、xUnitとNUnitの特別なサポートに加えて(例外ベースの単体テストフレームワークもサポートされていますが)、すべてのUnquote演算子はFSIセッション内でも機能します。

于 2011-04-14T20:28:26.753 に答える
3

Unquoteはまだ試していませんが、FsCheckについて言及する必要があると思います。http://fscheck.codeplex.com/ これ はHaskells QuickCheckライブラリの移植版であり、実行する特定のテストを指定するのではなく、何を指定するかを指定します。関数に関するプロパティが当てはまるはずです。私にとって、これは従来のテストを使用するよりも少し難しいですが、プロパティを理解すると、より確実なテストが可能になります。イントロダクションを読んでください:http://fscheck.codeplex.com/wikipage ?title = QuickStart&referringTitle = Home

FsCheckとUnquoteを組み合わせるのが理想的だと思います。

于 2012-02-25T23:50:17.330 に答える
2

私のユニットテストライブラリExpectoを試すことができます; それはあなたが好きかもしれないいくつかの機能を持っています:

  • 全体を通してF#構文、値としてテストします。プレーンなF#を記述してテストを生成する
  • 組み込みのExpectモジュール、またはアサーションにUnquoteなどの外部ライブラリを使用します
  • デフォルトの並列テスト
  • Hopacコードまたは非同期コードをテストします。Expectoは全体を通して非同期です
  • LogaryFacadeを介したプラグ可能なロギングとメトリック。ビルドシステム用のアダプターを簡単に作成するか、テストの実行時間のInfluxDB+Grafanaダッシュボードをビルドするためのタイミングメカニズムを使用します
  • BenchmarkDotNetの組み込みサポート
  • FsCheckのサポートを組み込みます。生成された/ランダムなデータを使用してテストを構築したり、オブジェクト/アクターの状態空間の不変モデルを構築したりするのが簡単になります

Helloworldはこのように見えます

open Expecto

let tests =
  test "A simple test" {
    let subject = "Hello World"
    Expect.equal subject "Hello World" "The strings should equal"
  }

[<EntryPoint>]
let main args =
  runTestsWithArgs defaultConfig args tests
于 2018-11-17T17:15:08.213 に答える