統合テストはいつ書くべきですか?


30

TDDユニットルールのルールによれば、製品コードの前に記述されていますが、具体的な(モックではない)ワイヤードオブジェクト間の相互作用を実行する統合テストについてはどうでしょうか。

「配線」をテストするためだけに、単体テストの前に作成するか、製品コードの後に​​作成する必要がありますか?

私は、受け入れテストや機能テストではなく、低レベルの統合テストについて話していることに注意してください。

回答:


49

Rspec Bookは、他のBDDリソースの中でも、次のようなサイクルを示唆しています。

ここに画像の説明を入力してください

基本的に、プロセスは次のとおりです。

While behaviour required
    Write an integration test for a specific behaviour
    While integration test failing
        Write a unit test to fulfil partial behavior
        While unit test failing
            Write code to make unit test pass
        Commit
        While refactoring can be done
            Refactor
            While unit test failing
                Write code to make unit test pass
            Commit
    Push

免責事項:これが最良のコードと製品につながることは疑いの余地がありませんが、時間がかかる可能性があります。統合テストは常にパスする必要があるということになると、データと決定論に関するあらゆる種類の困難があります。それはすべての状況で適切ではありません。ドアから物を取り出す必要がある場合もあります。

とはいえ、理想的なプロセスを念頭に置くことは素晴らしいことです。妥協点を示します。


2
@pdrに感謝しますが、反復の前/開始時に書かれた受け入れテストについて話していないことを明記しました。私はより低いレベルの統合テストに興味があります。
Chedy2149

@ chedy2149:Akkh。そのコメントを逃しました。回答を削除する前に、統合テストのコンテキストで「低レベル」とはどういう意味かをより具体的にすべきだと思います。
pdr

下位レベル:ユーザーまたはクライアントが指定しない動作、および開発者が期待するクラス/コンポーネントの相互作用をテストするために使用される動作。
Chedy2149

4
実際、その画像に「受け入れテスト」または「統合テスト」を入れても違いはないと思います。これは、さまざまな抽象化レベルのあらゆる種類のテストの理想的なビューです。しかし、IMHOの本当の問題は、これが「時間がかかる」ということではありません-本当の問題は、TDDの助けを借りて設計された公開インターフェースに対して「事前に」統合テストを書くことは、「動くターゲット「。
ドックブラウン

@DocBrownので、あなたの答えは製品コードの後、リリース前ですか?
Chedy2149

10

実際のプロジェクトでは、単体テストを作成してから統合することは不可能であり、反対の方向でさえ間違っていることが示されました。

どうして?両方の種類のテストの見方を書いてみましょう。

  1. 単体テスト -ウィキペディアとすべての既知の情報に加えて、単体テストは設計の絞り込み、モデル、関係の改善に役立ちます。フローは簡単です。新しいプロジェクト/新しいコンポーネントの入力を開始すると、ほとんどの場合、何らかのPoCを作成します。完了すると、常に長いメソッド、長いクラス、一貫性のないメソッドとクラスなどがあります。

    上記のモック(他のコンポーネントへの依存関係なし)クラスを使用して実際のユニットテストを行う場合はテストできないため、ユニットテストはこれらの問題を解決するのに役立ちます。テストできないコードの基本的な兆候は、多くの依存関係(または状況)を模擬することを余儀なくされるため、テストの大きな模擬部分です。

  2. 統合テスト -正しいテストと動作テストは、新しいコンポーネント(または複数のコンポーネント)が一緒にまたは他のコンポーネントと連携することをあなたに言います-これは通常の定義です。統合テストは、主に、消費者側からコンポーネントを使用する方法のフローを定義するのに役立つことがわかりました。

    APIは外部から意味をなさないと時々言うので、これは本当に重要です。

さて、後で単体テストと統合テストを書いたらどうなりますか?

素敵なクラス、明確なデザイン、優れたコンストラクター、短く一貫したメソッド、IoC対応などを取得しました。たとえば、統合またはGUIチームの開発者などの一部の消費者にクラス/ APIを渡すと、 、変だ。彼はただ混乱していた。そこで、彼の観点に従ってAPIを修復しましたが、メソッドの変更やAPIの使用方法の変更さえも求められたため、多くのテストを書き直す必要がありました。

さて、統合テストと単体テストを後で書いたらどうなりますか?

正確なフロー、使いやすさを得ました。また、大規模なクラス、非コヒーレントコード、ロギングなし、長いメソッドもあります。スパゲッティコード

私のアドバイスは何ですか?

私は次のフローを学びました:

  1. コードの基本的なスケルトンを開発する
  2. 消費者の観点から意味があるかどうかを示す統合テストを作成します。今のところ、基本的なユースケースで十分です。テストは明らかに機能しません。
  3. 各クラスのユニットテストと共にコードを記述します。
  4. 統合テストの残り/欠落を記述します。コードを改善する方法として、これらのテストを3番目の範囲内で実装することをお勧めします。

私が作ったことを注意小さなプレゼンテーション、ユニット/統合テストについての骨格が記述されているスライド#21を参照してください。


5

単体テストは、アプリケーション内のソフトウェアのテスト可能な最小ビットをテストし、その機能をテストするために使用されます。各ユニットは、アプリケーションのパーツまたはより大きなコンポーネントに統合する前に個別にテストされます。

そこで統合テストが行われます
。これらのパーツを合わせる際に、以前にテストされたユニットで構成されるこれらの新しく作成されたパーツをテストします。最善のケースは、アプリケーション自体を作成しながら、この時点でテストを作成することです。


あなたの答えは生産コードの後に​​ありますか?
Chedy2149

これは質問に答えません。彼は、統合テストの作成後に製品コードを作成するかどうかを尋ねています。あなたの答えはどちらの方法でも取ることができます。
Reactgular

1
@MathewFoscarini-更新された回答。今それがより明確になることを願っています。
ベンマクドゥーガル

単体テストに関しては、「ソフトウェアの可能な限り最小のビット」で問題になります。コントラクトは何が機能するかを定義するため、コントラクトの内容(たとえば、オブジェクトのパブリックメソッド、ライブラリのエクスポートされた関数)をテストします。他のことはテスト可能ですが、そうすることは時間の無駄だけでなく逆効果にもなります。
itsbruce

3

私は統合テストを単体テストに非常に似ていると見なす傾向があります。その点で、コードのサブセットをブラックボックスとして扱っています。したがって、統合テストは単なる大きな箱です。

量産コードの前にそれらを書くことを好みます。これには、まだ接続されていない部分や、オブジェクトの相互作用の詳細をわずかに変更したことを思い出すのに役立つという利点があります。


テストにはさまざまなレベルがあります:ホワイトボックスコンポーネントテスト、ホワイトボックス統合コンポーネントテスト。コンポーネントのブラックボックステスト、統合ブラックボックステスト。統合システムのテストもあります。
Alexander.Iljushkin

2

受け入れテストとは別に、私はアプリケーションの境界でのみ統合テストを記述し、サードパーティのシステムまたはコンポーネントとうまく統合できることを確認する傾向があります。

アイデアは、サードパーティが話す方法からアプリケーションが必要とするものに変換するアダプターオブジェクトを作成し、これらのトランスレーターを実際の外部システムに対してテストすることです。テストを先に行うかテストを最後に行うかは、通常の単体テストよりも重要ではないと思います。

  • TDDによって提供されるデザインの洞察は、デザインが事前にかなり知られており、通常はそれほど複雑ではなく、システム間をマッピングするだけなので、それほど重要ではありません。

  • 取り組むモジュール/システムに応じて、多くの調査、構成の調整、サンプルデータの準備が必要になる場合があり、時間がかかり、短いTDDフィードバックループにはあまり適合しません。

ただし、少し安全な手順で段階的にアダプターを構築する方が本当に快適だと感じる場合は、テストファーストにすることをお勧めします。

このアプローチの例はここで見つけることができます:http : //davesquared.net/2011/04/dont-mock-types-you-dont-own.html(6番目の段落) http://blog.8thlight.com/eric- smith / 2011/10/27 / thats-not-yours.html


ここでは、「私たちのシステム」とサードパーティのライブラリ間の相互作用を検証する統合テストについて説明しています。たとえば、プラグインの開発中にプラットフォームに対する相互作用をテストする方法についてはどうでしょうか。
Chedy2149

プラグイン開発の経験はほとんどありませんが、本質的にホストアプリケーションと密接に結合しているため、異なる可能性があります。そのため、その統合を完全に受け入れて、アダプターレイヤーは不要であると判断する場合があります。ただし、ホストアプリケーションによっては、テストの多くでAPIを直接呼び出すのが非常に遅くなる場合があります。あなたがそれを恐れているなら、あなたはいつでも「追加の抽象化レイヤー」アプローチに頼ることができ、アダプターでモック+統合テストを使用できます。
-guillaume31

1

だから私は最初の答えを受け入れるつもりだったが、それは削除された。 与えられた反復で
それを要約するには

  1. 単体テストを書く
  2. 製品コードを書く
  3. 統合テストを作成して相互作用をテストする

統合レベルでのテスト容易性を保証するために、1および2の統合テストを念頭に置いてください。

統合テストは、ステップ3で必ずしもエンドツーエンドで記述される必要はなく、ステップ1と2の間に部分的に記述される場合があります。


3
この要約は、プロセスの反復的な性質を完全に無視します。本番コードのAPIがある程度安定したら、統合テストの作成を開始できます。その後、本番コードで再度作業を行い、おそらく統合テストを変更または拡張できます。そのため、ほとんどの場合、「実動コードの後に​​統合テストを作成する」ことはありません。通常、両方をある程度並行して実行します。そして実際には、これはどのような種類のソフトウェアを使用しているかにも大きく依存しています。「白黒」思考はあなたをそれ以上連れて来ません。
Doc Brown

良い点:答えは、リファクタリングによる設計の反復的な性質を無視しているようです。
Chedy2149

0

ユニットテスト、プロジェクトのコードの個別ブロックをテストます。
統合テストは、コードが他のコードとどのようにインターフェイスするかをテストします。つまり、コードのインターフェイスをテストします

インターフェイスの背後にあるコードを開発するときに単体テストを作成します。
インターフェイスまたはインターフェイスを実装するコードを開発するときに統合テストを作成します。

これは、作業の大半がインターフェイスの背後にあるため、プロジェクトの非常に遅い段階で統合テストを作成することがあることを意味します。たとえば、コンパイラ、複数のロジック層を実装する特定のWebサービス、または内部ロジック。

ただし、一連のRESTサービスを実装するか、データモデルをリファクタリングしてXAトランザクションのサポートを追加する場合は、ほとんどの作業がインターフェイスに集中しているため、ほとんどすぐに統合テストの開発を開始しますREST APIまたはプログラムがデータモデルを使用する方法。


ユニットテストはホワイトボックステストであり、統合テストはブラックボックステストであると言うことに同意しますか?
Chedy2149

残念ながら、それは状況次第です。統合テストの技術は、近年(少なくともJavaの世界では)大幅に改善されているため、1つのクラスをテストできますが、アプリケーションサーバー上でテストできます。質問は次のようになります。単体テストと統合テストの境界はどこにあるのでしょうか?コードを他のテクノロジーとのインターフェイスをテストするときの統合テストですか、それともアプリケーション全体をテストするときの統合テストですか?ただし、必ずしも実行する予定の環境ではありませんか?
マルコ

要するに、場合によっては、統合テストがブラックボックステストであることを確認してください。ただし、すべての場合ではありません。
マルコ

FYI:ウィキは、「個々のソフトウェアモジュールを組み合わせてグループとして試験されたソフトウェアのテストの位相」としてintegraionテストを定義
マルコ

まさにマルコ。各コンポーネントレベルには統合があります。コードレベル、アプリケーションレベル、システムレベル。
Alexander.Iljushkin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.