外部APIを照会することが唯一の目的であるが、APIは複雑な照会構文を使用する関数をどのようにテストしますか?


16

唯一の実際のロジックは、外部APIのクエリ構文にあります。APIを照会するかどうかをテストするのではなく、正しいデータが返されるような方法で照会することをテストする必要があります。たとえば、いくつかの擬似コード:

function retrieve_related_data(id)
{
  query = "[potentially long, syntactically complex query that
            uses param id to get some data]";
  results = api_wrapper.query(query);
  return results;
}

構成されたAPIを使用したより具体的な例:

function retrieveLifeSupportingObjectsWithinRegion(id)
{
  query = "
    within region(" + id + ") as r
    find objects matching hydration>0 and temp_range has 75
    send name, id, relative(position, r)        
  ";
  results = astronomicalObjectApiWrapper.query(query);
  return results;
}

クエリはAPIの構文のカスタムであり、複雑であり、同じまたは類似の結果を達成するための複数の方法があります。この関数の目的は、特定されidたデータを取得することではなく、特定されたデータとのファジー関係に基づいて他のデータのサブセットを見つけることidです。他の要件は、関係なく常に同じですidが、システムが変更されると時間とともに変化する可能性があります。たとえば、サンプルAPIで重力情報のサポートが追加された場合、結果を絞り込むために重力も使用するようにクエリを変更できます。または、温度範囲を確認するより効率的な方法を考え出すかもしれませんが、結果は変わりません。

私がテストしたいのは、与えられた入力idに対して正しいデータセットが返されることです。私はこれをテストして、誰かがクエリを台無しにして、id失敗に基づいて正しいデータを返さないようにしたいのですが、また、クエリを修正して、修正する必要なくクエリを改良できるようにしたいですテスト。

私が検討したオプション:

  1. APIをスタブすることはできますが、それは単純すぎます(idクエリに存在することを確認し、存在する場合は予期されるデータセットを返し、そうでない場合は予期しないセットを返します)、あまりにも脆弱です(クエリ文字列がまさに機能である)、または複雑すぎる(使用クエリは文法的に正しいことを確認し、正しいデータになります)が返されます。

  2. クエリを実際のAPIに送信することはできますが、テストシステムの制御外で外部システムのデータが変更されると、予想される結果が時間とともに変化する可能性があります。

  3. 実際のAPIのデータを制御するために、実際のAPIのテストインストールをセットアップすることもできますが、それは多大な労力です。

私は#2に傾いており、これをより頻繁に実行されない統合テストにし、外部システムのデータの変更がテストを中断させる頻度を確認しています。今のところそれは最も簡単だと思いますが、私が考えていない代替案や、この問題に取り組むためのより良い方法があるかどうか疑問に思っています。アドバイスをいただければ幸いです。


私はこれを単体テストと考えていましたが、実際には統合テストまたは低レベルの受け入れテストでしょうか?
ジョシュアコーディ

2
読み取り専用APIですか?または、読み取りを確実に検証できるデータを書き込むことができますか?
svidgen

この質問は、「sql(= complex syntax)が正しいデータを返すことをテストする方法」とは異なりますか?データベースでは、通常、crud-sql-syntaxと模擬リポジトリファサードをテストして、ビジネスロジックを検証する統合テストがいくつかあります
k3b

回答:


7

外部API応答を検証することで機能をテストしているように見えるかもしれませんが、完全に真実ではありません。どういうわけか、外部APIとAPIが実行されている環境をテストすることになります。

私たちのテストは、サードパーティによって書かれたものではなく、私たちが書いたコードの予想される動作を保証するために対処されるべきです。

ある程度、依存するAPIとライブラリの適切な機能を信頼する必要があります。たとえば、通常、実装するフレームワークコンポーネントはテストしません。

なぜそう言うのですか?

私がテストしたいのは、与えられた入力IDに対して正しいデータセットが返されることです

ここで何をテストしますか?あなたが言ったように、データとその正確性は私たちの管理下にないため、テスト段階の成功を、私たちが管理できない外部エージェントに制限することになります。これらのテストは、非決定的かつ決定的になる候補であり、この種のテストを構築パイプラインに含めることは望ましくありません

別の懸念は、契約を検証することです。リリースまたはデプロイの前に、統合が期待どおりに機能していることを確認するために、契約テスト1が非常に役立つことがわかります。

誰かがクエリを台無しにして、失敗したIDに基づいて正しいデータを返さないようにするために、これをテストしたい

クエリは問題ないが、APIのバグによりデータが間違っている場合はどうなりますか?データが制御できないだけではありません。ロジックもそうです。

ここでは、機能テストまたはエンドツーエンドテストの実装が役立つ場合があります。これらのテストに対処して特定の実行パスを検証すると、APIが誤ったデータを返した場合、予期しない動作や出力が発生する可能性があります。一方、クエリの形式が正しくない場合、APIがエラーをスローすることを期待します。

しかし、テストを修正することなく、クエリを修正して改良できるようにしたいのです。

そのような目的でツールを実装することをお勧めします。それは次のように簡単かもしれません:

  • テストとして実行されるが、テスト計画に属さないクラス
  • シェルスクリプト+ curl

またはもっと洗練されたもの。たとえば、スタンドアロンクライアント。

いずれにせよ、問題の関数は、2種類のテストの価値があります。

  • 単体テスト。あなたが言ったように、外部APIをスタブ化する必要がありますが、それがユニットテストの目的です。依存関係を分離するコードをテストします。

  • 統合テスト。コードが正しいリクエストを送信するだけでなく、応答コンテンツ、エラー、リダイレクトなどを適切に処理することを確認します。これらのすべてのケースについてテストを行いますが、データはテストしません

サイドノート:あなたの質問は-アプリのSQLステートメントをどのようにテストしますか?

関連する質問


1:このトピックに関する@DocBrownの回答に興味があるかもしれません


「問題(IMO)は、外部APIのテストに集中しすぎていることです。」-質問者が外部APIのテストに興味があることを示すものはまったく表示されません。また、「外部APIをスタブする」と言いますが、質問者が「単純すぎる」オプション、「脆すぎる」オプション、「複雑すぎる」オプション、または4番目のオプションのいずれを使用すべきかについての提案はありますか?
タナースウェット

OPの質問は、外部APIを呼び出す関数をテストする方法を尋ねています。しかし、彼の疑問を読んで、彼はクエリとその結果のテストにあまりにも重点を置いているように思えます。私は4つの提案をしました:(1)APIのテストをしません。(2)クエリを調整するためのワークベンチとして統合テストを使用しないでください。代わりにツールを作成します。(3)主な質問に戻って、単一性と統合テストを行います。ただし、API応答のコンテンツは検証しません。(4)プロジェクトのテスト計画の一部として外部APIのテストスイートを作成する必要があるかどうかをプロジェクトマネージャーに尋ねます。
ライヴ

1
クエリ自体を「私たちが書いたコード」と考えています。最終目標は、コードにバグを導入した場合に警告する自動テストです。あなたがSQLステートメントについて言ったことにそれを当てはめると、私はそれと似ていると思います-私の質問は、APIが意図したとおりに応答する方法でコードが外部APIをクエリしていることをどのようにテストするのですか?公称応答)。あなたが言っていることはユニットと統合テストからそれを除外することだと思いますが、クエリがミッションクリティカルな場合、ライブ外部APIをテストするためにいくつかの他の自動化されたテストを設定できます。
ジョシュアコーディ

1
IMOは、機能テストを行うのが最善の方法です。where句の変更は決して真実ではないため、1つ以上の機能テストで異なる動作を引き起こします。UTはテスト計画のほんの一部です。
ライヴ

2
響きのボードに感謝します。最終的に、クエリにはカスタムロジックが含まれていますが、クエリはテスト対象のシステムの外部で「実行」されるコードであるため、ユニットテストの領域外です。私はそれを見る前に異なる方法で複数回それを私に言うために誰かが必要でした;)
ジョシュア・コーディ

2

生成されたクエリ文字列が期待値と一致することを確認するユニットチェックを見てきました。

しかしながら。使用が制限されている場合、これは私の意見でした。クエリ構文は複雑で、バグの可能性があるため、Aはチェックする無限の可能性があり、Bは文字列が「正しく」生成されたとしても、ライブ環境で予期しない結果が返される可能性がありました。

あなたはあなたの選択肢に行くのが正しいと思います。2.ライブインスタンスに対して統合テストを実行します。

それらが非破壊的である限り、これらはエラーの原因を特定することはできませんがキャッチするため、最初に記述する必要のあるテストです。

オプション3の「ダミーデータを使用してテストインスタンスを展開する」の方が優れています。ただし、テストの作成に影響はありません。テストサーバーを展開するのに時間がかかる場合は、テストサーバーで同じテストを指定できます。


0

APIに依存しますが、可能であれば、オプション#3(プライベートテストインスタンス)に進みます。

APIのスタブ(オプション#1)は、あなたが言及した理由のために最悪のオプションであり、このルートをたどることは、おそらく良い(多くの時間の浪費)よりも多くの害を及ぼします。

実際のAPI(オプション#2)に対して実行すると、テストは不安定で信頼性が低くなり、いくつかの誤検知の後、人々はテストの使用をやめます。データを変更できるだけでなく、サービスもダウンする可能性があります。私の意見では、これはクエリのテストがなく、問題を見つけるために統合/システムテストに依存していることに似ています。とはいえ、APIデータがめったに変更されず、API自体がほぼ常に稼働している場合、これは実行可能なオプションである可能性があります。ほとんどのAPIはこの説明に適合しません。

最終的には、これらのクエリがどれほど重要かつ複雑であるかということになります。ほんの一握り以上で、テストする必要があると感じるほど複雑なクエリがある場合は、テスト用にプライベートインスタンスをセットアップする労力を投資します。 。他の単体テストと同じように、それ自体に費用がかかります。


基本的に、単体テスト(#1)と統合テスト(#2)は有害であると言っていますか?#3が最高のように思えるかもしれませんが、これも最も高価になる可能性があります。APIが変更されるたびに維持する必要があります。#2がなければ、アプリが実稼働するまで、実際のAPIのバグ変更の可能性に気付かないでしょう(対策を取るには遅すぎます)。わかりました、#1はテストするコード行がないため不要です...今日...明日、方法は知っています
...-Laiv

悪いテストは間違いなく有害だと言っています。不安定なテストは多くの時間と労力を無駄にし、全体として単体テストに対する信頼を失います。実装の変更で中断するテスト(#1)、またはデータの変更でランダムに中断するテスト(#2)は適切なテストではありません。
ミハルテネンバーグ

統合テストはデータをテストしません。それでおしまい。彼らはテストを破ることができず、統合を検証するだけです。テストは信頼の問題ではありません。アプリケーションに価値を追加する良い習慣を持っていることの問題です
Laiv
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.