web-dev-qa-db-ja.com

F#開発と単体テスト?

私は最初の関数型言語であるF#を使い始めました。私はC#をほぼ独占的に使用してきましたが、F#を使用してコードの書き方を再考する方法をたくさん楽しんでいます。少し見当違いなのは、コードの記述プロセスの変更です。私は今までC#で何年もTDDを使用してきましたが、私がどこにいるかを知るための単体テストがあることを本当に感謝しています。

これまでのところ、F#での私のプロセスは、いくつかの関数を記述し、それらが機能することを「合理的に」確認できるまで対話型コンソールで操作し、調整および結合することでした。これはオイラープロジェクトのような小規模な問題ではうまく機能しますが、そのように大きなものを構築することは想像できません。

人々はどのように単体テストに取り組み、F#プログラムのテストスイートを構築しますか? TDDに相当するものはありますか?すべてのポインタや考えは大歓迎です。

104
Mathias

テスト駆動型の開発者は、F#のような関数型言語でくつろいでいるはずです:決定論的に再現可能な結果を​​もたらす小さな関数は、単体テストに完全に役立ちます。 F#言語には、テストの作成を容易にする機能もあります。たとえば、 Object Expressions をご覧ください。インターフェイスタイプを入力として受け取る関数の偽物を非常に簡単に書くことができます。

どちらかといえば、F#はファーストクラスのオブジェクト指向言語であり、C#でTDDを実行するときに使用するものと同じツールとトリックを使用できます。 F#で作成された、またはF#専用のテストツールもいくつかあります。

Matthew Podwysockiは、関数型言語の単体テストについて素晴らしい series を書きました。ボブおじさんも、考えさせる記事を書いた here

74
Ray Vernagus

私はNUnitを使用していますが、読むのが難しく、書くのが面倒ではありません:

open NUnit.Framework

[<TestFixture>]
type myFixture() = class

    [<Test>]
    member self.myTest() =
       //test code

end

私のコードはF#と他の.Net言語が混在しているため、ユニットテストを基本的に同じ方法で、F#とC#の両方で同様の構文で記述しているという事実が気に入っています。

22
David Glaubman

F#の自動テストツールであるFsCheckを見てください。これは基本的にHaskellのQuickCheckの移植版です。関数またはメソッドが満たす必要があるプロパティの形式でプログラムの仕様を提供し、ランダムに生成された多数のケースでプロパティが保持することをFsCheckテストできます。

FsCheck CodePlexページ

FsCheck Authorページ

15
primodemus

これは非常に興味深い質問だと思います。これまでの私の考えは単なる考えであるため、それらが何であるかを考えてください。

自動テストスイートのセーフティネットは手放すには貴重な資産であると思いますが、インタラクティブコンソールは魅力的かもしれないので、これまでと同じように単体テストを書き続けるつもりです。

.NETの主な強みの1つは、言語間の機能です。私はすぐにF#プロダクションコードを作成することを知っていますが、私の計画は、C#で単体テストを作成して、新しい言語を理解するのを容易にすることです。このようにして、F#で記述したものがC#(および他の.NET言語)と互換性があることをテストすることもできます。

このアプローチでは、F#コードで内部的にしか使用できないが、パブリックAPIの一部として公開できないF#の特定の機能があることを理解していますが、特定のことがあることを今日受け入れるように、私はそれを受け入れますC#を使用すると、CLSに準拠していない(uintなど)を表現できるため、使用を控えます。

11
Mark Seemann

Dglaubmanが示唆するように、NUnitを使用できます。 xUnit.net もこれをサポートし、 TestDriven.net と連携して動作します。コードはNUnitテストに似ていますが、テストを包含型でラップする必要はありません。

#light

// Supply a module name here not a combination of module and namespace, otherwise
// F# cannot resolve individual tests nfrom the UI.
module NBody.DomainModel.FSharp.Tests

open System
open Xunit

open Internal

[<Fact>]
let CreateOctantBoundaryReordersMinMax() =
    let Max = VectorFloat(1.0, 1.0, 1.0)
    let Min = VectorFloat(-1.0, -1.0, -1.0)

    let result = OctantBoundary.create Min Max

    Assert.Equal(Min, result.Min)     
    Assert.Equal(Max, result.Max) 
11
Ade Miller

FSUnit をご覧ください。まだ使用していませんが、試してみる価値はあります。たとえば、F#で(ネイティブ)NUnitを使用するよりも確実に優れています。

7
ShdNx

パーティーに少し遅れましたが、私はマティアスをF#に迎えて(決して遅くはありません;))、チャイムにExpectoが好きかもしれません

Expectoにはいくつかの機能があります。

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

-

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

https://github.com/haf/expecto/

1
Henrik