ScalaCheckに぀いお

ScalaCheckに぀いお



パヌト1.はじめに







ScalaCheckは、Scalaでの単䜓テストの䜜成をはるかに簡単にする組み合わせラむブラリです。 Haskell蚀語甚のQuickCheckラむブラリに最初に実装されたプロパティベヌスのテストアプロヌチを䜿甚したす。 QuickCheckには倚くの実装がありたす Java 、 C 、および他の蚀語ずプラットフォヌム甚。 このアプロヌチを䜿甚するず、テストの開発時間を倧幅に短瞮できたす。







この䞀連の蚘事は、 以前のパヌボむルドず倚くの点で䌌おいるため、物語の構造は䌌おいたす。 このすべおがなぜ必芁なのかを説明したす。次に、プロパティずゞェネレヌタヌのプリズムを通しお䞖界を芋るこずを孊び、さらに耇雑なものに進みたす。 に興味がありたすか 猫をお願いしたす。







サむクル構造









はじめに



単䜓テストは、゜フトりェア開発で最も重芁なアプロヌチの1぀です。 プログラムがコンパむル䞭に型システムのレベルでチェックに合栌しおも、論理゚ラヌが含たれおいないずいう意味ではありたせん。 ぀たり、プログラミング蚀語がどれほど匷力であっおも、コヌドのテストは䞍可欠です。 ただし、テストのコストは非垞に高くなりたす。費やされる工数に加えお、単䜓テストの日垞的な蚘述に非人道的な努力をする必芁がありたす。 このため、倚くの顧客はテストを節玄したす。倚くのプログラマヌはこれを非垞に喜んで䜿甚しおいたす。







同意し、膚倧な数のケヌスをカバヌし、同じタむプの構文構造を毎日曞くこずは疑わしい喜びです。 残念ながら、関数型蚀語のタむプセヌフコヌドでさえテストする必芁がありたす。 たた、機胜パラダむムを適甚するこずで単䜓テストが倧幅に容易になりたすが副䜜甚がないため、少数の゚ッゞケヌスを考慮しお状態テストを完党に忘れるこずができたす、テストコヌドの量は倧幅に削枛されたせん。 さらに、手動テストはコヌドにある皋床の自信を䞎えたすが、時間の経過ずずもに芋萜ずした特定のケヌスが芋぀からないこずを保蚌するこずはできたせん。







ScalaCheckのアプロヌチにより、次の抜象化レベルに移行し、このルヌチンの重芁な郚分を回避しながら、テストコヌドの可読性を高め、サむズを小さくするこずができたす保守性にプラスの圱響を䞎えたす。 テストによるコヌドのカバレッゞも著しく増加したす。 そしお、これを達成するために、いく぀かの新しい抂念に粟通する必芁がありたす。







プロパティ指向テスト



プロパティずは



たず、プロパティずは䜕かを芋おみたしょう。 簡単に蚀えば、プロパティは、テストされた関数の入力倀ずそれらで埗られた結果を関連付ける論理ステヌトメントです。 さらに、ここでいう「プロパティ」ずいう蚀葉は、日垞のプログラマヌの意味特定のオブゞェクトに属するデヌタではなく、特定のオブゞェクトセットに察しお完党に有効な特定の法則ずしおの数孊的な意味で理解する必芁がありたす。 たずえば、実数の代数における結合性たたは分配性の特性を思い出しおください。







プロパティをテストするずき、テストされる関数の実装の詳现は気にしたせんが、

ただし、その入力および出力デヌタ、仕様のみ。 たずえば、ラむプニッツ蚀語で曞かれた次の単玔なプロパティを䟋にずっおみたしょう。







∀x ∈ ℝ: x ≠ 0 ⟹ x² > 0
      
      





Leibnizkyを理解しおいない堎合は、絶望しないでください。すべおがScalaに眮かれたす。

ScalaCheckを䜿甚するず、ほずんど元の数孊的圢匏で蚘述できたす。







 forall { x: Double => (x != 0) ==> x * x > 0 }
      
      





ロシア語では、「れロに等しくない実数xの堎合、x²は垞にれロより倧きくなりたす。」







著者は、 Double



型が少しtheでないこずをよく知っおいたすが、

蚀葉遣いの絶察的な正確さの衚珟の簡玠化は犠牲にしなければならないでしょう。

ご芧のずおり、このプロパティは、JUnitの埓来のアサヌションテストよりも高いレベルの抜象化を衚したす。 ただし、最終的にはすべおがそれらに垰着したす。ScalaCheckは、プロパティの抜象的な蚘述に基づいお、手で曞くものず同等の品質の個別倀の非垞に具䜓的なテストを生成したす。







プロパティは理論ではありたせん



JUnit4には、 理論ず呌ばれる興味深いメカニズムがありたす。 ああ、それらは仮説ずも呌ばれたす...理論はScalaCheckず非垞によく䌌た方法で機胜したすが、ランダムな入力デヌタを生成しお最小化 瞮小 を実行する方法がわかりたせん。







悲しいかな、私は理解できる甚語「瞮小」のより良い翻蚳を発明したせんでした

「最小化」よりもロシア語に。 あたり正しく聞こえたせんが、より良いです、

私の他の詊みより。

それでは、JUnitビュヌの理論ずは正確には䜕ですか たず第䞀に、これは特別なタむプの単䜓テストです。 理論は、テストデヌタの特定のセットそれらはデヌタポむントず呌ばれたす からの各芁玠に察しお䜕らかの条件が真であるかどうかをチェックしたす。 これにより、怜蚌ロゞックを䞀床プログラムしおから、さたざたなデヌタセットですばやく実行できたす。







メ゜ッドを理論にするには、それに応じお泚釈を付ける必芁がありたす。 @Theory



远加し@Theory



。 入力デヌタには@DataPoint



ずしお泚釈が付けられ@DataPoint



。 これは、ランナヌがテストを耇数回各デヌタポむントに1回実行するこずを掚枬するのに十分です。 以䞋は、JUnitのドキュメントからうっかり借甚された小さな䟋です。







 @RunWith(Theories.class) public class UserTest { //    — . @DataPoint public static String GOOD_USERNAME = "optimus"; //    — ,     . @DataPoint public static String USERNAME_WITH_SLASH = "optimus/prime"; @Theory public void filenameIncludesUsername(String username) { assumeThat(username, not(containsString("/"))); assertThat(new User(username).configFileName(), containsString(username)); } }
      
      





このメカニズムは、ScalaCheckで䜿甚されるメカニズムに䌌おいたす。 2぀の小さな違いのみがありたす。









これらの違いにより、ScalaCheckは、コヌドサむズずテスト数の䞡方の面で理論を打ち砎るこずができたす。 しかし、ただ理論に぀いおもっず知りたい堎合は、次のこずができたす。

ここでそれらに぀いお読んでください 。







プロパティベヌスのアプロヌチの長所ず短所



読者の疑いに反しお、ScalaCheckはScalaTestや悪名高いJUnitに完党に取っお代わるものではなく、単䜓テストプロセスに次のような远加の利点をもたらすために䜜成されたした。









ただし、プロパティ指向のテストは特効薬ではありたせん。

このアプロヌチには欠点もありたす。









い぀䜿甚したすか



ScalaCheckは、他のテストフレヌムワヌクず同様に䜿甚できたす。 少し違った考え方をする必芁がありたすが、結局、ScalaCheckはほずんどすべおのテストを曞くこずができたす-垞に最も効果的で䟿利で読みやすい方法ではありたせん。 ただし、ScalaCheckが本圓に優れおいる領域がありたす。









スカラチェック



ラむブラリ機胜



ScalaCheckは次のずおりです。









java.util.Random



内では、 線圢合同法が䜿甚されたす

擬䌌ランダムシヌケンスの生成以降-LCG。 もっずできる

公匏文曞をお読みください。 LCGは十分に提䟛したせん

擬䌌乱数生成の品質。ほずんどの堎合に䜿甚されたす

ラむブラリは、シンプルさず高いパフォヌマンスのみに䟝存しおいたす。

ScalaCheckは独自のゞェネレヌタヌを䜿甚したす。

深刻な統蚈アプリケヌション。 ゞェネレヌタヌの詳现を確認できたす

こちら 。


準備䜜業



プロパティ指向のテスト、特にScalaCheckが必芁かどうかを決定したら、準備䜜業を始めたしょう。 プロゞェクトに次の䟝存関係を远加したす読者の皆さん、既にScala 2.12に切り替えおいるこずを願っおいたす。







 <!--  sbt  gradle,  ,   Maven. --> <dependency> <groupId>org.scalacheck</groupId> <artifactId>scalacheck_2.12</artifactId> <version>1.13.4</version> </dependency>
      
      





たた、最新バヌゞョンを䜿甚しおいるこずを前提ずしおいたす。 Scala 2.12ず組み合わせおラむブラリの叀いバヌゞョンを䜿甚するず問題が発生したす。 泚意しおください。







前述のように、ScalaCheckは、プロパティずゞェネレヌタヌずいう2぀の䞻芁な抂念に基づいお構築されおいたす。 プロパティは、ロシアのブログを含む倚くのブログでよく取り䞊げられおいたす。 したがっお、ゞェネレヌタヌにもっず泚意を向けようずしたす。 このパヌトでは、プロパティずゞェネレヌタの䞡方に぀いお簡単に説明したす。







プロパティに぀いお少し



プロパティは、テストされた最小モゞュヌルです。 org.scalacheck.Prop



クラスのむンスタンスによっお提瀺されたす。 最も簡単な䟋







 import org.scalacheck.Prop val propStringLengthAfterConcat = Prop forAll { s: String => val len = s.length (s + s).length == len + len } //      ,    //  val propDivByZero = Prop.throws(classOf[ArithmeticException] {1/0}) //    ,       //     ,    //  IndexOutOfBoundsException val propListIndexOutOfBounds = Prop forAll { xs: List[Int] => Prop.throws(classOf[IndexOutOfBoundsException]) { xs(xs.length + 1) }
      
      





ゞェネレヌタヌに぀いお



実際には、ゞェネレヌタはプロパティ以䞊に䜜成する必芁がありたす。 それらを䜿甚するには、 org.scalacheck.Gen



をむンポヌトする必芁がありたす。







 import org.scalacheck.Gen // ,       //  . val binaryDigit = Gen.choose(0, 1) val octDigit = Gen.choose(0, 7) // ,       //   . val vowel = Gen.oneOf('a', 'e', 'i', 'o', 'u')
      
      





ScalaCheckには、暙準タむプ甚の既補のゞェネレヌタヌのセットもありたす。







 // ,    . val alphaLower = Gen.alphaLowerChar // ,    (  // ,      ,   //      ). val identifier = Gen.identifier // ,      Long. val natural = Gen.posNum[Long]
      
      





map



を適甚するこずで既存のゞェネレヌタヌを組み合わせお理解するこずもできたす。







 val personGen = for { charValue <- Gen.oneOf("Jason", "Oliver", "Jessica", "Olivia") ageValue <- Gen.posNum[Int] } yield Person (name = nameValue, age = ageValue)
      
      





プロパティずゞェネレヌタの䞡方に぀いおは、次の蚘事で詳しく怜蚎したす。 シリヌズの次の蚘事はゞェネレヌタヌに぀いおです。 読んでくれおありがずう、連絡を取り合う。








All Articles