ユニットテストの進化

単体テストの書き方について、そして一般にTDDの利点について多くの言葉が言われています。 その後、いくつかのBDDが地平線上に現れました。 どちらが優れているのか、それらの違いは何かを把握する必要があります。 おそらくこれが、ほとんどの開発者が気にせず、どちらか一方を使用しないことに決めた理由でしょうか?



簡単に説明すると、BDDはTDDのアイデアをさらに発展させたものであるため、使用する必要があります。 そして、TDDとBDDの違いを簡単な例で説明しようとします。



1つの実際のプロジェクトで見つけた1つの単体テストの3つの改訂を検討してください。



試行番号1



この単体テストの最初のバージョンは次のとおりです。



public class ReferenceNumberTest { @Test public void testValidate() { assertFalse( ReferenceNumber.validate("1234567890123") ); assertFalse( ReferenceNumber.validate("1234567") ); assertTrue( ReferenceNumber.validate("12345678") ); } }
      
      





これを典型的な単体テストと呼びます。 彼はコードをテストしますが、それ以上のものはありません。 そうでない任意のメリットよりももっと。 このコードの後に​​、単体テストは特に有用ではないと懐疑論者が結論付けています。



試行番号2



ある時点で、開発者が来て、このコードを適用することを決定し、いくつかの「 :ベストプラクティス TDDの」:いくつかの小さな上のスプリットテスト方法、それらのそれぞれが、一つだけをテストし、それらに適切な名前を与えられるように。



それは彼が得たものです。

 public class ReferenceNumberTest { @Test public void testTooLong() { String len13 = "1234567891111"; assertEquals(len13.length(), 13); assertEquals(ReferenceNumber.validate(len13), false); } @Test public void testTooShort() { String len7 = "1234567"; assertEquals(len7.length(), 7); assertEquals(ReferenceNumber.validate(len7), false); } @Test public void testOk() { String len8 = "12345678"; assertEquals(len8.length(), 8); assertEquals(ReferenceNumber.validate(len8), true); String len12 = "123456789111"; assertEquals(len12.length(), 12); assertEquals(ReferenceNumber.validate(len12), true); } }
      
      







良い単体テストと呼んでいます。 読むためにはるかに簡単です:変数の名前で13文字ことを推測することは容易である - これは正常です - 少なすぎると8文字 - それはあまりにも多く、7です。



試行番号3



しばらくして、別の開発者がやって来て、この優れた単体テストでさえも完全に読み取り可能ではなく、ReferenceNumberクラスがどのように機能するかについて十分な情報を提供していないことに気付きます。 あなたはそれを理解することができますが、このためにはまだコードに入り、少し考える必要があります。



開発者は、分割と名前変更のプロセスを継続します。



 public class ReferenceNumberTest { @Test public void nullIsNotValidReferenceNumber() { assertFalse(ReferenceNumber.validate(null)); } @Test public void referenceNumberShouldBeShorterThan13() { assertFalse(ReferenceNumber.validate("1234567890123")); } @Test public void referenceNumberShouldBeLongerThan7() { assertFalse(ReferenceNumber.validate("1234567")); } @Test public void referenceNumberShouldContainOnlyNumbers() { assertFalse(ReferenceNumber.validate("1234567ab")); assertFalse(ReferenceNumber.validate("abcdefghi")); assertFalse(ReferenceNumber.validate("---------")); assertFalse(ReferenceNumber.validate(" ")); } @Test public void validReferenceNumberExamples() { assertTrue(ReferenceNumber.validate("12345678")); assertTrue(ReferenceNumber.validate("123456789")); assertTrue(ReferenceNumber.validate("1234567890")); assertTrue(ReferenceNumber.validate("12345678901")); assertTrue(ReferenceNumber.validate("123456789012")); } }
      
      







これBDDスタイル仕様と呼びます。 メソッドの名前は、コードがどのように機能するかについてほとんど人間の言語を話します。 大文字の前に精神的にスペースを挿入すると、英語でコードの仕様が得られます。 クラスがどのように機能するかを理解するために、コードに入るべきではなく、タイトルを読むだけです。 コードの過程で、それがミスを犯し、ユニットテストが壊れ変更した場合と、我々は、おそらく我々はコード内の間違いの種類を決定することができるようになります壊れたテストメソッドに名前を付けます。



ちなみに、タリンで開催されたBDDに関するdevclub.euセミナーで、このユニットテストの進化の例を紹介しました。 ですから、セミナーの前日、 ReferenceNumberクラス自体のソースコードをコピーするのを忘れたことに気付きました。 どうする パニック! セミナーの前日! 急いで自分で書き直す必要がありました。



次に、これら3つのテストクラスを見て、ReferenceNumberクラスのロジックを復元するのにどれが役立ったかを考えてください。





そして最後に、BDD



3番目のバージョンはクラスの動作を説明する点で以前のバージョンとは異なると言えます。 これは、と«含む»「べき」などの単語を使用することによって達成される:«私のクラスはとても-と、そう振る舞うべきだ」、 『私の方法はとても-と、そうします』。



だから、BDDのアイデアは、言葉«テスト»とは«主張»を«すべき»の言葉«仕様»を使用し、正確であると。 はい、違いは言葉だけではあるが、それはBDDの著者によれば、そしてコードに読みやすい仕様と書き込みテスト仕様書を作る-人間の脳のための自然。



JUnitからEasybに翻訳された同じ例を見ると、これを確認できます。

 description "ReferenceNumber" it "should not be null", { ReferenceNumber.validate(null).shouldBe false } it "should be shorter than 13", { ReferenceNumber.validate("1234567890123").shouldBe false } it "should be longer than 7", { ReferenceNumber.validate("1234567").shouldBe false } it "should contain only numbers", { ReferenceNumber.validate("1234567ab").shouldBe false ReferenceNumber.validate("abcdefghi").shouldBe false ReferenceNumber.validate("---------").shouldBe false ReferenceNumber.validate(" ").shouldBe false } it "valid reference number examples", { ReferenceNumber.validate("12345678").shouldBe true ReferenceNumber.validate("123456789").shouldBe true ReferenceNumber.validate("1234567890").shouldBe true ReferenceNumber.validate("12345678901").shouldBe true ReferenceNumber.validate("123456789012").shouldBe true }
      
      







これらの仕様テストの開始に関するレポートは、実際にはドキュメントとして役立ちます。

5.31 KB



さらにそれとべきで、BDDでは、このような良く、とき、その後、だけでなく、前後に、与えられた、しかも確実に、物語と«として振る舞うべき»など、他の重要な言葉は、あります。 BDDは単体テストだけでなく、機能/統合テストにも適していますが、これはすでにこの記事の範囲外です。 ここで、単体テストのレベルに関心があります。 この記事の目的は、さまざまな方法で記述できることを示すことです。





BDD仕様を記述するためのライブラリは、Java( JDaveJBehave )、Ruby( RSpecRBehaveCucumber )、Groovy( Easyb )、Scala( Scala-test )、PHP( Behat )、CPP( CppSpec、. NetSpecFlowShouldly )、Python( レタスキュウリ )。

あなたの理由及ばない状況に起因して、あなたが何か他のものへのJUnitから変更できない場合 - のいずれか何も、ちょうど第三の例については覚えています。 ところで、この場合、 Harmcrestライブラリは役に立ちます。



コズマ・プルトコフが遺したように:同志、BDDi!






All Articles