複雑なAPI(たとえばAmazon S3)に依存するコードをテストする方法は?


13

Amazon S3にドキュメントをアップロードするメソッドのテストに苦労していますが、この質問は重要なAPI /外部の依存関係に当てはまると思います。考えられる解決策は3つしかありませんが、満足できるものはありません。

  1. コードを実行し、実際にドキュメントをアップロードし、AWSのAPIでアップロードされたことを確認し、テストの終了時に削除します。これにより、テストが非常に遅くなり、テストを実行するたびに費用がかかり、常に同じ結果が返されません。

  2. モックS3。私はそのオブジェクトの内部についてはまったくわからないので、これは非常に毛深いです。

  3. MyObject.upload()が正しい引数で呼び出されることを確認し、S3オブジェクトを正しく使用していることを信頼してください。テストだけではS3 APIを正しく使用したかどうかを確実に知る方法がないため、これは気になります。

Amazonが独自のSDKをテストし、彼らがすべてを模擬する方法を確認しました。彼らは、モックを行う200行のヘルパーを持っています。私が同じことをするのが実際的だとは思わない。

これをどうやって解決しますか?


答えではありませんが、実際には、公開した3つのアプローチを使用します。
jlhonora

回答:


28

ここで検討しなければならない問題が2つあります。

1つ目は、単体テストの観点からすべてのテストを見ているように見えることです。単体テストは非常に価値がありますが、唯一のテストではありません。テストは実際には非常に速いから、いくつかの異なる層に分けることができますユニットテスト少なく、高速に統合テストでも遅くに受け入れテスト。(機能テストのように、さらに多くのレイヤーが分割される可能性があります。)

2つ目は、サードパーティのコードへの呼び出しをビジネスロジックと組み合わせて、テストの課題を作成し、コードをより脆弱にする可能性があることです。

単体テストは高速で、頻繁に実行する必要があります。依存関係のモックは、これらのテストを高速に実行し続けるのに役立ちますが、依存関係が変更され、モックが変更されない場合、カバレッジにホールが生じる可能性があります。テストがまだ緑色で実行されている間に、コードが破損する可能性があります。依存関係のインターフェイスが変更された場合に警告するモックライブラリもあれば、できないものもあります。

一方、統合テストは、サードパーティライブラリを含むコンポーネント間の相互作用をテストするように設計されています。実際のオブジェクトがどのように相互作用するかを確認するため、このレベルのテストではモックを使用しないでください。実際のオブジェクトを使用しているため、これらのテストは遅くなり、ユニットテストほど頻繁には実行されません。

受け入れテストでは、さらに高いレベルで、ソフトウェアの要件が満たされているかどうかをテストします。これらのテストは、展開される完全なシステム全体に対して実行されます。繰り返しますが、モックは使用しないでください。

モックに関して価値があるとわかったガイドラインの一つは、自分が所有していないタイプをモックしないことです。AmazonはS3のAPIを所有しているため、S3の下でAPIが変更されないようにすることができます。一方、あなたはこれらの保証を持っていません。したがって、テストでS3 APIをモックアウトすると、コードが変更されて破損する可能性がありますが、テストはすべて緑色で表示されます。では、サードパーティのライブラリを使用するコードをどのように単体テストするのでしょうか?

まあ、私たちはしません。ガイドラインに従うと、所有していないオブジェクトをモックすることはできません。しかし…直接的な依存関係を所有している場合、それらをモックすることができます。しかし、どのように?S3 APIの独自のラッパーを作成します。S3 APIによく似た外観にすることも、ニーズにさらに近づけることもできます(推奨)。私たちも言って、それはもう少し抽象的な作ることができるPersistenceServiceのではなくをAmazonS3BucketPersistenceService以下のようなメソッドとのインタフェースになる#save(Thing)#fetch(ThingId)、我々は(これらは、あなたが実際には別の方法をお勧めします、例です)見たいかもしれない方法の種類。これでPersistenceService、S3 APIの周りにを実装して(たとえばS3PersistenceService)、呼び出しコードからカプセル化することができます。

次に、S3 APIを呼び出すコードについて説明します。これらの呼び出しをPersistenceServiceオブジェクトの呼び出しに置き換える必要があります。依存性注入を使用PersistenceServiceして、オブジェクトに渡します。それは重要だないために依頼するS3PersistenceService、しかしを求めることPersistenceService。これにより、テスト中に実装を交換できます。

直接S3のAPIを使用するために使用されるすべてのコードは、今、私たちを使用していますPersistenceServiceし、私たちはS3PersistenceService今、S3のAPIへのすべての呼び出しを行います。テストではPersistenceService、所有しているので、モックアウトでき、モックを使用してコードが正しい呼び出しを行うことを確認します。しかし、今ではテスト方法が残っていますS3PersistenceService。以前と同じ問題があります。外部サービスを呼び出さずに単体テストを行うことはできません。そのため、ユニットテストは行いません。我々は可能性が S3のAPIの依存関係をモックが、これは私たちに少しツーなし追加の自信を与えるだろう。代わりに、より高いレベルでテストする必要があります:統合テスト。

これは、コードの一部を単体テストしてはならないという厄介な問題に聞こえるかもしれませんが、達成したことを見てみましょう。単体テストができなかった場所に、大量のコードがあり、今ではを通じて単体テストを行うことができますPersistenceService。単一の実装クラスに限定されたサードパーティライブラリの混乱があります。そのクラスは、APIを使用するために必要な機能を提供する必要がありますが、外部ビジネスロジックはアタッチされていません。したがって、一度作成すると、非常に安定しているはずであり、あまり変更しないでください。コードが安定しているため、それほど頻繁に実行しないより遅いテストに頼ることができます。

次のステップは、の統合テストを作成することですS3PersistenceService。これらは名前またはフォルダで分離する必要があります。これにより、高速ユニットテストとは別に実行できます。統合テストでは、コードが十分な情報を提供している場合、単体テストと同じテストフレームワークを使用できることが多いため、新しいツールを学ぶ必要はありません。統合テストの実際のコードは、オプション1用に記述するものです。


問題は、公開するAPIの統合またはむしろe2eテストをどのように実行するかです。明白な理由でPersistenceServiceをモックすることはできません。どちらか私の誤解何か、またはアプリケーションAPIとAWS APIの間に別の層を追加することで、あなたにもっと簡単に時間ユニットテストをやってたよりも何も与えない
Yerken

@Yerken私はそれについて考えているので、私はその質問に対する別の長い答えを記入できると確信しています。あなたは私の応答以上のものを得るかもしれないので、それはあなたにとっても価値があるかもしれません。
cbojar

4

両方を行う必要があります。

実行、アップロード、削除は統合テストです。これは外部システムとインターフェースするため、実行速度が遅くなることが予想されます。ローカルで行うすべてのビルドの一部ではないはずですが、CIビルドまたはナイトリービルドの一部である必要があります。これにより、これらのテストの遅延が相殺されますが、自動的にテストされるという価値があります。

また、より高速に実行される単体テストも必要です。一般に、外部システムに強く依存しすぎないようにするのが賢明なので(実装を交換したり、切り替えたりできるようにするため)、おそらくコーディング可能なS3を介した簡単なインターフェイスを作成する必要があります。ユニットテストでそのインターフェイスをモックして、迅速に実行できるユニットテストを作成できるようにします。

最初のテストでは、コードが実際にS3で動作することを確認し、2番目のテストでは、コードがS3と通信するコードを正しく呼び出すことを確認します。


2

APIの使用の複雑さに依存すると思います

  1. S3 APIを実際に呼び出して、エンドツーエンドで機能することを確認するテストを少なくともいくつか行う必要があります。

  2. また、実際にAPIを呼び出さない追加のテストを行う必要があるため、常にAPIを呼び出すことなく、独自のソフトウェアを適切にテストできます。

残る質問は、APIをモックする必要があるかどうかです。

そして、それはあなたがどれだけそれをするかにかかっていると思います。1つまたは2つの単純なアクションだけを実行している場合、モックアップのすべての問題に取り組む必要はないと思います。関数の使用を確認し、ライブテストを行うだけで満足です。

ただし、結果に影響を与える可能性のあるさまざまなシナリオとさまざまな変数を使用して、その使用がより複雑な場合は、おそらくより徹底的なテストを行うためにモックアップする必要があります。


1

前の回答に加えて、主な質問は、テスト用にS3 APIをモックするかどうか(およびその方法)です。

個々のS3応答を手動でモックする代わりに、非常に洗練された既存のモックフレームワークを利用できます。たとえば、motoは、実際のS3 APIに非常によく似た機能を提供します。

また、既存のツールを組み合わせ、統合テストを容易にする完全に機能するローカルクラウド環境(S3を含む)を提供するフレームワークであるLocalStackを確認することもできます。

これらのツールの一部は他の言語(Python)で作成されていますが、たとえばJava / JUnitのテストから外部プロセスでテスト環境を簡単に起動できるはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.