過去数年間、主にF#で関数型プログラミングを行ってきた開発者として、私は自分のREPLに非常に愛着があり、それを使用してコードを実行し、各関数をテストおよび改良しますただし、開発者として私がよく失敗する1つの領域は、すべての関数の優れた単体テストを作成し、最初のコードレビューリクエストで提出することです。
よりOOP/C#のバックグラウンドを持っている私のチームの他の開発者は、REPL駆動ではないワークフローを使用しており、ユニットテスト(MSTEST)を使用してREPLで行う実験的なテストを行っています。これにより、サイクルの終わりに一連の単体テストが残りますが、プロジェクトをビルドして毎回テストエンジンを待つ必要がなく、反復とテストをはるかに迅速に行えるため、REPLを優先します。
私たちはF#チームであるため、REPLは開発中の実験的テストに適したツールですが、ビルド中に正式な単体テストを実行する必要があると考えています。ゲートチェックインプロセス。単体テスト用のテストクラスとテストメソッドを作成する必要があるため、他の場所ではクラスをあまり頻繁に使用しないので、私は特にそれが好きではありませんが、対処できます。すべてのビルドで繰り返し可能な一連のテストを実行して、重大な変更をすぐに指摘することの価値は、OOPテストフレームワークの特異性に対処するのに十分です。
いくつかの研究を行っているとき、私は Cursive IDE for Clojure for a REPL with clojure.test
フレームワークを使用して、REPLで記述したコードを単体テストにすることができます。これは理想的なソリューションのようであり、F#テストプロジェクトのように見えます Expecto はこのパターンを部分的にサポートしている可能性があるため、試してみることを検討しています。ただし、利用可能な最善のソリューションでない限り、ワークフローとテストプロセスに破壊的な変更を加えたくありません。
テストツールを変更せずにこれを解決できる、見落としている単純なワークフローの変更はありますか? REPLと単体テストは、他の大規模なFPベースのプロジェクトでどのように使用されますか?
Read-Eval-Print Loop(REPL) 開発は、「成長する」使用可能な関数に関係する必要があります。単体テストでは、これらの関数をテストして、正しく機能することを確認する必要があります。ユニットテストを作成するために必要な追加の作業を除いて、基本的にこれら2つのアイデアに矛盾はありません。
単体テストを作成する方法は常に2つあります。テスト対象のコードを作成する前と後のどちらかです。 テスト駆動開発 は、従来はテストファーストでしたが、おそらくREPLがもたらす利点をすべて排除します。これで、それぞれのユニットテストを記述できるようになります。あなたの中間REPLステップの、これはあなたを遅くするでしょう。
だからここが私がお勧めするものです。関数を記述した後、ユニットテストを記述します。関数が何を行うかを理解します(つまり、仕様を作成します) 関数ごとに)、REPLテクニックを使用して関数を記述し、それに従ってユニットテストにラップします仕様。言い換えれば、単体テストは、関数がその仕様、指定された要件を満たすことを実証する必要があります。
これにより、REPLが提供する迅速な開発を妨げることなく、現在のワークフローに最小限の変更を加えるだけで、ユニットテストの利点が得られます。
もちろん、Expectoを同じ方法で使用することを妨げるものは何もありません。これまでに説明したのと同じワークフローを使用します。 Expectoには、パフォーマンステスト、ストレステスト機能、複数のコアをサポートする機能、クラスを必要としないテストなど、MSTestにはない多くの利点があるようです。
open Expecto
let tests =
test "A simple test" {
let subject = "Hello World"
Expect.equal subject "Hello World" "The strings should equal"
}