🔨 テストデータビルダによる保守可能なテスト


リファクタリングし、テストを変更する時間を過ごす?何がテストをしないか?テストデータビルディング救助に!

🧪 テストとメンテナンス


ほとんどの開発者はテストの重要性を理解している.テストを安全に1をリファクタリングできます.
これらの開発者は、保守可能なコードが非常に重要であることを知っています.テストコードにとってこれが重要であることを知っている人は少ない.テストが保守できない場合、これは負の効果を持ちます.リファクタリングはより困難になり、最終的には悪い生産コード1につながる.

十分に保守的なテストの2つの原因は以下の通りです.
  • は、テストの重複によるあまりに多くのカップリング.
  • 非明示的な
  • テスト.
  • なぜこれらの側面がテストコードの保全性に影響するのかを見てみましょう.

    🔗 結合の痛み


    あなたはおそらくそれを経験しました:何かコードで変更される必要があります.問題は、後でテストを調整する時間を過ごすことです.
    どうして?
    テストは結合の形です.彼らは、我々の生産コードをどのように呼び出すことができますか?余分なパラメータを導入するなど、コード内の署名を変更するときに問題が発生します.結合は、それから痛いほど明確になります:コードのその部分を使用するすべてのテストを調節しなければなりません.
    生産コードでは、“Don’t Repeat Yourself”の原則に準拠し、これをテストする際に、しばしば困難です.単にオブジェクトのバリエーションが必要です.これは、プロダクションコードよりもテストでオブジェクトをより頻繁に作成する理由です.これは微妙な形式の複製につながります.

    図1.オブジェクト生成によるテストの結合
    結合のこの形はテストの保全性に否定的な影響を与えます、しかし、それは我々が気をつける必要がある唯一のものでありません..

    🗣️ 表現力テストの重要性


    読みやすいコードは重要です.良い開発者は、それが書かれるよりしばしばコードが読まれるということを理解します.
    テストは読者がコードの動作を理解するのを助ける.そういうわけで、彼らはドキュメンテーションの効果的な形として勤めます.
    残念ながら、これはいくつかの努力をします.テストが効果的にコードの動作を説明するためには、主な問題から主を分離することが重要です.
    簡単.テストで最も重要なことは、(行動)ではなく、どのように(メカニズム)です.リスト1では、テストされた動作がテストメカニズムから分離されていないため、非明示的なテストの例が表示されます.
    @Test
    void an_unreadable_test() {
        Country country = new Country("USA", Currency.US_DOLLAR, Language.ENGLISH);
        Author author = new Author("Oscar Wilde", country);
        Novel novel = new Novel(
                "The picture of dorian gray",
                50.00,
                author,
                Language.ENGLISH,
                Lists.newArrayList(Genre.MYSTERY)
        );
        PurchasedBook book = new PurchasedBook(novel, 1);
        Invoice invoice = new Invoice("test", country);
    
        invoice.addPurchasedBook(book);
    
        assertEquals(56.35, invoice.computeTotalAmount());
    }
    
    
    リスト1 .非表現テスト;意図はメカニズムによって隠される
    これらのことが正しく分離されていない場合、テストは何が起こっているかを教えてくれません.これは、読者がそれを理解するためにより長くかかるか、より悪い、彼らはそれを変更することを恐れになる.幸いにも、それはそれを取得する必要はありません、テストデータビルダーのおかげで.

    👷 テストデータビルダとは


    Test Data BuildersBuilder Patternの形態であるが、テスト2のオブジェクトを作成するために適用される.これらのビルダーは、安全で論理的な既定値を持つオブジェクトを作成します.通常のビルダーパターンのように、オブジェクトは変更可能なメソッドを提供します.
    このパターンは必ずしも適用できない.特にValue Objects or Entitiesに対して複雑な物体構造の作成に有効である.
    利点に加えて、欠点もある.これらのビルダーを自分で書き、維持しなければならないので、バグが発生します.すべてのためにすぐにビルダーを作りませんが、重量挙げをしてください!

    ✨ テストデータビルダのテスト


    テストデータビルダーは、その表現力を高める一方、あなたの生産コードからより多くのテストコードを分離するのに役立ちます.それはほとんど魔法のように聞こえます、しかし、あなたが後でわかるように、それは本当にありません.

    🎊 減結合


    テストデータビルダは、オブジェクトの構築をカプセル化することによって結合の問題を解決します.ビルダーを使用してテストの対象を作成し、この場所が発生する場所の数を減らします.引数を追加した場合は、今必要なのはビルダーのコードを変更することです!

    図2.オブジェクト生成からのテストデータビルダ(TDB)分離テスト

    🎉 増加した表現性


    また、非表示テストの問題は、テストデータビルダによって解決される.安全なデフォルトでオブジェクトを作成するので、テストの適切な値を調整する必要があります.つのプロパティを検証したいとしましょう.次に、オブジェクトを作成するときにオーバーライドする唯一のものは、残りは問題ではありません.あなたが技術的な“混乱”を減らすこの方法は、テストをもっと伝える!リスト1を例2のリストに比較します.
    @Test
    void increased_readability_by_test_data_builder() {
        Invoice invoice =
            anInvoice()
                .from(USA)
                .with(
                    aPurchasedBook().of(aNovel().costing(50.0))
                ).build();
    
        assertEquals(56.35, invoice.computeTotalAmount());
    }
    
    
    リスト2 .テストデータビルダーがテスト意図を公開

    🎁 ボーナス:テストDSL


    追加の利点は、ビルダーメソッドを使用すると、ドメインの詳細について話すことができます.リスト1をリスト2と比較すると、ビルダーメソッドがコンストラクター呼び出しまたはプロパティの設定以上を伝えることがわかります.あなたがよくビルダーの方法を命名するならば、あなたはテストのためにDomain Specific Languageで終わります!

    📝 ラッピング


    テストは良いコードベースにとって重要ですが、保守性がなければ変更を難しくすることができます.これは、テストでのカップリング、または表現できないテストによるものです.
    テストデータビルダは、両方の問題に解決策を提供します.テストデータを1つの場所で大きく構築することが可能となり、過度の結合を防ぐことができます.また、彼らはより良いテストの意図を表示することができます.
    どんなパターンでも、それらを使用することを考慮するとき、あなたは欠点を考慮するべきです.あなたがこの権利を行うならば、彼らはあなたのテストをより保守的で表現力豊かにします!
    次回テストを書くときは、この効果的な解決策を思い出してください.それはあなた自身とあなたのチームに簡単に!
    テストデータビルダとの経験は何ですか?他の長所や短所を見ますか.コメントでお知らせください!
    マーティン, F .リファクタリング既存コードの設計改善(アディソンWesley Signature Series(Fowler))(第2版)アディソンWesleyプロ.朱
    フリーマン、S .、Pryce、N .オブジェクト指向ソフトウェアの成長,テストによる誘導(第1版)アディソンWesleyプロ.朱