1. ホーム
  2. unit-testing

[解決済み] ScalaTestとScala Specsのユニットテストフレームワークの違いは何ですか?

2022-08-31 18:37:18

質問

どちらもScalaで書かれたBDD(Behavior Driven Development)対応のScala用ユニットテストフレームワークです。また スペック を含むこともあります。 ScalaTest フレームワークを使うこともあります。しかし、SpecsはScalaTestにないものを提供しているのでしょうか?その違いは何でしょうか?

どのように解決するのか?

SpecsとScalaTestはどちらもハッピーなユーザーを持つ良いツールですが、いくつかの点で異なっています。おそらくScalaのメインテストツールとしてどちらかを選びたいでしょうが、両方の断片を使うことができるので、もう一方をあきらめる必要はないでしょう。もし、ScalaTestの FeatureSpec の構文とspecsのMockitoの構文が好きなら、例えば、両方のjarファイルをクラスパスに置いて、両方を同時に使うことができます。ここでは、specsとScalaTestの間で私が気づいた主な設計思想の違いを整理してみたいと思います。

両ツールの主な哲学的な違いは、specsが行動駆動開発(BDD)のために設計されているのに対し、ScalaTestはより一般的なものであるということだと思われます。ScalaTest は、BDD を含むテストクラスで好みの動作を得るために混ぜることができる特性を提供し、また、異なるものを望むなら、独自の動作を簡単に定義することができます。

ScalaTestはBDDをサポートするために Spec , FeatureSpec , WordSpec , FlatSpec そして GivenWhenThen といった trait があり、また、それらを混ぜることで良い Matcher 構文を得ることができます。もし、"should" が好きなら、ShouldMatcherを混ぜればいい。もし、"must" が好きであれば MustMatchers . しかし,BDDは好きだけど,マッチャーの構文は好きじゃないという人は,マッチャートラットを混ぜずに,ScalaTestのSpecトライットの一つを使えばいい.Specs には継承する Specification クラスがあり,マッチャー式では "must" という単語を使用しなければなりません.ここで明らかになる大きな哲学的な違いは、ScalaTestはより多くの選択肢を与えてくれるということです。この選択の空間をナビゲートしやすくするために、ここでディシジョンツリーを提供します。

http://www.scalatest.org/quick_start

Matcher の構文も ScalaTest と specs では異なります。ScalaTest では、演算子表記でどこまでできるか試してみましたが、結局、単語と単語の間にスペースがある、英語の文章によく似た matcher 式を作りました。SpecsのMatcher構文は、キャメルケースでより多くの単語を並べます。

SpecsはScalaTestよりも多くのマッチャーを持っていますが、これは設計姿勢の違いを反映していると思います。実際に、私が構築し、リリースを検討した matcher 構文のうち、おそらく 2/3 をカットしました。将来のリリースではさらに多くの matcher を追加する予定ですが、追加する前に、ユーザーが実際に何かを求めていることを確認したかったのです。しかし、ScalaTestのmatcherには動的なプロパティのmatcher構文が含まれており、その不足分を補うことができます。例えば,Specs では java.io.File :

file must beDirectory

これは isDirectory を呼び出して、それが真であることを確認します。ScalaTest では java.io.Files に対する特別なマッチャーはありませんが、ScalaTestではこのような動的なチェックを使うことができます。

file must be a ('directory)

の後にシンボルを渡すと、いつでも be の後にシンボルを渡すと、リフレクションを使って、 (この場合) directory という名前のメソッドやフィールド、あるいは isDirectory . また、これを静的にする方法もあります。 BePropertyMatcher (を定義することで、これを静的にする方法もあります(これは通常2、3行のコードしか必要としません)。ですから、基本的にScalaTestでは、より少ないAPIでより多くの機能を提供するように心がけています。

specとScalaTestの間のもう一つの一般的な設計態度の違いは、暗黙の変換です。 は暗黙の変換を含んでいます。ScalaTestを使う場合,デフォルトでは暗黙の変換は1つだけです. === 演算子をつけるものです。(必要であれば、1行のコードでこの暗黙の変換をオフにすることができます。そうする必要がある唯一の理由は、もしあなたが独自の === 演算子を持つものをテストしようとしていて、衝突してしまった場合です)。ScalaTestは他にも多くの暗黙の変換を定義していますが、それらを使うには、traitを混ぜたりimportをしたりして、明示的にコードにそれらを招待する必要があります。クラスを拡張する場合 Specification のような暗黙の変換は、デフォルトで何十個もあると思います。このことが実際にどの程度問題になるかはわかりませんが,人々は独自の暗黙知を使用するコードをテストしたいと思うでしょうし,時にはテストフレームワークの暗黙知と本番コードの暗黙知の間で衝突が起こるかもしれません.そのような場合、SpecよりもScalaTestで問題を回避する方が簡単だと思います。

私が気づいた設計姿勢のもう一つの違いは、演算子に対する快適さです。私が持っていた一つの目標は、ScalaTestを使用している他の人のテストコードを見ているプログラマーが、ScalaTestのドキュメントで何も調べなくても、その意味が推測できるようにすることでした。ScalaTestのクライアントコードは、一目瞭然であってほしかったのです。この目標は、ScalaTestが演算子に対して非常に保守的であることに表れています。私はScalaTestで5つの演算子しか定義していません。

  • === というのは、イコール
  • > よりも大きいことを意味します。
  • < よりも小さいことを意味します。
  • >= より大きいか等しい
  • <= , 小または等しい

これで終わりです。つまり、これらのものはほとんど意味のように見えます。他の人のコードで見ると

result should be <= 7

私の望みは、API ドキュメントにアクセスしなくても、その <= が何を意味するのかを推測するために API ドキュメントに走る必要がなくなることを期待しています。それに対して、specsは演算子に対してずっと自由です。それはそれで悪いことではないのですが、やはり違います。演算子はコードを簡潔にすることができますが、その代償として ->- , >> , | , |> , ! または ^^^ (これらはすべて Specs で特別な意味を持ちます) を使って、同僚のテストコードに追加してください。

もう一つの哲学的な違いは、フィクスチャを共有する必要があるときに、ScalaTest では関数型スタイルを使うことをほんの少し簡単にしようと思っているのですが、Specs ではデフォルトで setUptearDown というアプローチは,JUnitによって一般化されたもので,各テストの前にバーを再割り当てするものです.しかし、もしその方法でテストをしたいのであれば、ScalaTestでは非常に簡単です。ただ BeforeAndAfter を混ぜるだけです。

ScalaTestに関するより深い洞察については、2009年のDevoxxカンファレンスで私が行ったプレゼンテーション、 "Get Higher with ScalaTest" をこちらでご覧いただけます。

http://parleys.com/play/514892260364bc17fc56bde3/chapter0/about