ラップトップではAPIが問題なく動作し、ローカルのテストクライアントではすべてのチェックに合格しました。しかし、チームメイトがブランチをマージし、デプロイが行われると、これまで200を返していたエンドポイントが、本番環境で500を返すようになりました。誰もそれに気づきませんでした。なぜなら、そのブランチでテストを実行した人がいなかったからです。彼らは一度、手動でマシン上でテストを実行しただけでした。
「テストが存在する」と「すべての変更でテストが実行される」というギャップを埋めるのが、まさにCIパイプラインです。コードがすでにAzure ReposまたはGitHubにあり、チームがAzure DevOpsで開発している場合、Azure Pipelinesはそのセーフティネットを構築するのに最適な場所です。難しいのはYAMLではありません。APIテストスイートを、適切な環境で、新しくデプロイされたビルドに対してヘッドレスでパイプラインが実行できる形にし、何か問題が発生した場合にはビルドを明確に失敗させることです。
ボタン
TL;DR
- Azure Pipelinesは、コミットまたはPRごとにAPIテストを自動的に実行するため、回帰はリリースされる前に検出されます。
- Apidogでテストシナリオを視覚的に構築し、手動でテストスクリプトを記述・保守する代わりに、Apidog CLI (
apidog-cli) を使用してCIで実行します。 - パイプラインには4つのものが必要です: エージェントにNode.jsがインストールされていること、CLIがインストールされていること、リンクまたはエクスポートされたファイルを介してテストシナリオにアクセスできること、そしてシークレットとして保存されたアクセストークン。
- CLIからのゼロ以外の終了コードは、自動的にビルドを失敗させます。これにより、真のゲートが提供されます。
- HTMLまたはJUnitレポートをパイプラインアーティファクトとして公開する (または
PublishTestResultsを使用する) ことで、誰でもログを開かずに合否を確認できます。
「Azure Pipelinesでの自動APIテスト」が実際に意味するもの
Azure Pipelinesは、Azure DevOps内のCI/CDサービスです。リポジトリに保存されているYAMLファイル (azure-pipelines.yml) でビルドを記述すると、プッシュ、プルリクエスト、スケジュール、または手動実行など、トリガーが発動するたびにAzureがそのファイルをホスト型またはセルフホスト型エージェントで実行します。

APIテストの場合、ジョブの形はシンプルです。
- エージェント (クリーンなVM) を起動します。
- テストランナーが必要とするものをすべてインストールします。
- ターゲット環境に対してAPIテストを実行します。
- 結果を報告し、それに基づいてビルドステータスを設定します。
人々が躓くのはステップ3の詳細です。ローカルのAPIクライアントは対話型です。「送信」をクリックし、応答を目で確認し、緑色のチェックマークを読みます。パイプラインにはクリックする人も、目で確認する人もいません。人間を介さず、GUIなしで同じアサーションを実行する方法が必要です。それこそが、コマンドラインランナーが存在する理由です。
CIの概念についてより広範な入門が必要な場合は、最初のパイプラインを構築する前に、継続的インテグレーション、継続的デリバリー、継続的デプロイの違いをざっと読んでおくと良いでしょう。
なぜApidogでテストを設計し、CLIで実行するのか
APIテストは生のコードで記述することもできます。言語を選び、HTTPライブラリとアサーションフレームワークを取り込み、リクエストボディを手動で作成し、応答を解析し、認証トークンを管理し、スプリントごとに変更されるAPIとこれらすべてを同期させるのです。チームはこれを行っています。そして、その保守に不釣り合いなほどの時間を費やしています。
Apidogは異なるアプローチを取ります。あなたはテストシナリオを視覚的に構築します。リクエストを連鎖させ、ある応答からのデータを次のリクエストに渡し、ステータスコード、ヘッダー、JSONフィールドにアサーションを追加し、複数のデータ行で同じシナリオを駆動させます。ApidogはすでにAPI定義を保持しているため、テストは仕様に密接に結びついています。スキーマが変更された場合、本番環境で発見する代わりに、そのズレを視覚的に確認できます。

この視覚的な作業をCIに接続する要素が、npmで公開されているコマンドラインランナーであるApidog CLIです。これは保存されたテストシナリオをヘッドレスで実行し、結果を反映したステータスコードで終了します。すべて合格した場合は0、いずれかのアサーションが失敗した場合はゼロ以外の値です。この終了コードは、すべてのCIシステムが理解する契約です。Azure Pipelinesはこれを読み取り、ビルドがグリーンかレッドかを決定します。GUIで一度設計すれば、同じシナリオがパイプラインで変更なく実行されます。

これは、GitHub Actions、GitLab CI、Jenkinsで機能するのと同じモデルです。Azure Pipelinesは、同じCLIコマンドの別のホストにすぎません。つまり、チームがプラットフォームを切り替えても、その知識は転用できます。
前提条件
パイプラインを構築する前に、これらを準備してください。
- 少なくとも1つのテストシナリオを含むApidogプロジェクト。テストシナリオセクションを開き、シナリオを作成し、いくつかのリクエストを追加し、アサーションを添付します。ローカルで一度実行し、合格することを確認します。もしローカルで不安定な場合、CIでも不安定になります。
- Apidogアクセストークン。CLIはApidogアカウント設定の個人アクセストークンで認証します。これをパスワードのように扱い、パイプラインシークレットとして保存し、YAMLには決して保存しないでください。
- リポジトリを持つAzure DevOpsプロジェクト。
azure-pipelines.ymlはリポジトリのルートに配置されます。 - Node.jsの知識 (軽度)。CLIはNode上で動作するため、エージェントにはNodeがインストールされている必要があります。Azureのホスト型エージェントにはすでにインストールされています。バージョンを選択するだけです。
- 到達可能なターゲット環境。テストは実行中のAPI(ステージングURL、プレビューデプロイ、またはパイプライン自体が起動するサービス)にアクセスする必要があります。トリガーを記述する前に、どれを使用するかを決定してください。
テスト対象のターゲットについて簡単に説明します。コミットごとに本番環境に対してスイートを実行するのはリスクが高く、多くの場合不可能です (本番環境にテストデータを入れたくはないでしょう)。ほとんどのチームはCIテストをステージング環境またはブランチごとのプレビューデプロイに向けます。Apidogの環境はこれをクリーンにします。独自のベースURLと変数を持つStaging環境を保持し、実行時にCLIにどれを使用するかを指示します。
ステップ1:テストシナリオを実行可能な形式にする
CLIは実行すべきシナリオを知る必要があります。Apidogは、シナリオを供給する2つの方法を提供します。
オプションA、共有オンラインリンクから実行する。Apidogでテストシナリオを開き、CLI経由で実行することを選択すると、Apidogはネットワーク経由でシナリオを指すコマンドを生成します。これはメンテナンスの手間が少ないオプションです。パイプラインは常にシナリオの現在のバージョンを実行し、テストファイルをリポジトリにコミットする必要がありません。トレードオフは、パイプラインが実行時にそのリンクに到達できるかどうかに依存することです。
オプションB、シナリオをファイルにエクスポートしてコミットする。シナリオ(とその環境)をローカルファイルにエクスポートし、コードと一緒にコミットし、CLIをそのファイルパスに指定します。これにより、テストは特定のコミットに固定されます。再現性を重視する場合にこれが望ましいです。実行されたテストは、そのコミットにあるテストとまったく同じものになります。トレードオフは、シナリオが変更されるたびに再エクスポートする必要があることです。
ほとんどのチームが開始する際には、オプションAの方が早く設定できます。規制が厳しく監査が多い作業の場合、オプションBの再現性が優位です。また、組み合わせることも可能です。迅速に動くフィーチャーブランチにはリンクベースを、リリースブランチにはファイルベースを使用するなどです。
どちらの方法でも、Apidogが提供する正確な実行コマンドをメモしておいてください。それは次のように表示されます。
apidog run https://api.apidog.com/api/v1/test-scenarios/<scenario-id> \
-t <access-token> \
-e <environment-id>
最もよく使用するフラグは次のとおりです。
- シナリオ参照(オンラインリンクまたはローカルファイルパス)
- 認証用の
-t/ アクセストークン - 実行対象の環境を指定する
-e - 出力形式を制御するためのレポーターオプション(CLIテキスト、HTML、または機械可読なサマリー)
- データセットをループさせたい場合の繰り返し回数
Apidogが生成するシナリオの実行コマンドと、正確なフラグ名を確認してください。ランナーはapidog run --helpで利用法を表示します。フラグを推測せず、Apidogが提供するものをコピーし、シークレットをパラメータ化してください。
ステップ2:まずCLIがローカルで動作することを確認する
CI内で新しいツールをデバッグしないでください。パイプラインのフィードバックループは遅く、ログはターミナルよりもノイズが多いです。まず自分のマシンでグリーン実行を確認してください。
CLIをインストールします。
npm install -g apidog-cli
次にシナリオを実行します。
apidog run https://api.apidog.com/api/v1/test-scenarios/<scenario-id> \
-t "$APIDOG_ACCESS_TOKEN" \
-e "<staging-environment-id>"
以下の3つのことを確認します。
- コマンドが完了し、合否のサマリーが出力されること。
- 終了コードが結果と一致すること。直後に
echo $?を実行します。成功時には0、失敗時には非ゼロであるべきです。 - 環境が正しく解決されていること。リクエストが、残っていたローカルなURLではなく、ステージングURLにヒットしていること。
この終了コードの確認は、見た目以上に重要です。アサーションが失敗してもCLIが0で終了する場合、パイプラインは壊れたコードでもグリーンになってしまい、テストがまったくないよりも悪い状況になります。一度意図的に失敗を発生させ(アサーションをわざと壊し)、非ゼロコードが得られることを確認してください。その後、アサーションを元に戻します。
ステップ3:Azure Pipelines YAMLを作成する
リポジトリのルートにazure-pipelines.ymlという名前のファイルを追加します。ホスト型Ubuntuエージェント用の完全で動作する出発点です。
trigger:
branches:
include:
- main
- develop
pr:
branches:
include:
- main
pool:
vmImage: ubuntu-latest
variables:
NODE_VERSION: '20.x'
steps:
- task: NodeTool@0
inputs:
versionSpec: $(NODE_VERSION)
displayName: 'Install Node.js'
- script: npm install -g apidog-cli
displayName: 'Install Apidog CLI'
- script: |
apidog run https://api.apidog.com/api/v1/test-scenarios/$(SCENARIO_ID) \
-t $(APIDOG_ACCESS_TOKEN) \
-e $(STAGING_ENV_ID)
displayName: 'Run API tests'
解説:
triggerは、mainおよびdevelopへのプッシュごとにパイプラインを実行します。ブランチ名に合わせて調整してください。prは、mainをターゲットとするプルリクエストで実行します。これは、壊れたブランチがマージされるのを阻止するゲートです。pool/vmImageは、MicrosoftホストのUbuntuエージェントを選択します。インフラの管理は不要です。NodeTool@0は、特定のNodeバージョンをインストールし、実行の再現性を確保します。- インストールステップは、実行ごとにCLIを新しく取得します。より速いビルドのために
node_modulesをキャッシュしたりバージョンを固定したりできますが、まずはシンプルに始めましょう。 - 重要なのは実行ステップです。いずれかのアサーションが失敗した場合、
apidog runは非ゼロで終了し、スクリプトタスクが失敗し、ビルド全体が赤色になります。
$(...)参照はパイプライン変数です。SCENARIO_ID、STAGING_ENV_ID、そして特にAPIDOG_ACCESS_TOKENは、ここにハードコードされるのではなく、次のステップから取得されます。
ステップ4:シークレットを正しく保存する
アクセストークンをYAMLに平文で置くべきではありません。リポジトリに読み取りアクセスできる人なら誰でもそれを見ることができ、あなたのApidogプロジェクトへのアクセスを許可してしまいます。
シークレットパイプライン変数を使用します。
- Azure DevOpsで、パイプラインを開き、編集、次に変数(または共有変数グループの場合はライブラリ)を選択します。
APIDOG_ACCESS_TOKENを追加し、トークンを貼り付けます。- ロックアイコンを切り替えて、シークレットとしてマークします。Azureはこれを暗号化し、ログでマスクします。
シークレット変数は自動的にシェル環境に注入されるわけではありません。ステップ内で明示的にマップする必要があります。実行ステップを更新して、envを介してシークレットを渡すようにします。
- script: |
apidog run https://api.apidog.com/api/v1/test-scenarios/$(SCENARIO_ID) \
-t $(APIDOG_ACCESS_TOKEN) \
-e $(STAGING_ENV_ID)
displayName: 'Run API tests'
env:
APIDOG_ACCESS_TOKEN: $(APIDOG_ACCESS_TOKEN)
SCENARIO_IDとSTAGING_ENV_IDはシークレットである必要はありません。これらは可読性のために通常の変数として扱うか、複数のパイプラインで再利用する変数グループに移動してください。多くのシークレットを管理するチームの場合、Azure Key Vaultで変数グループをバックアップし、ローテーションが一箇所で行われるようにします。
ステップ5:読みやすいテストレポートを公開する
赤いビルドは何か壊れたことを示しますが、何が壊れたかは教えてくれません。解決策は、CLIにレポートを出力させ、Azureにそれを表示させることです。
Apidog CLIは、その結果をレポートファイルに書き込むことができます。出力形式 (人間にはHTML、Azureのネイティブテストビューを使いたい場合はJUnit形式のXML) と出力ディレクトリを指定し、そのディレクトリを公開します。
人間が読めるアーティファクトの場合:
- script: |
apidog run https://api.apidog.com/api/v1/test-scenarios/$(SCENARIO_ID) \
-t $(APIDOG_ACCESS_TOKEN) \
-e $(STAGING_ENV_ID) \
-r html \
--out-dir $(Build.ArtifactStagingDirectory)/api-report
displayName: 'Run API tests'
env:
APIDOG_ACCESS_TOKEN: $(APIDOG_ACCESS_TOKEN)
- task: PublishBuildArtifacts@1
condition: always()
inputs:
pathToPublish: $(Build.ArtifactStagingDirectory)/api-report
artifactName: api-test-report
displayName: 'Publish API test report'
2つの注目点があります。1つ目は、condition: always()により、テストステップが失敗した場合でも公開ステップが実行されることです。何か問題が発生したときに最もレポートが必要になるため、これが重要なポイントです。2つ目は、CLIのバージョンに対してapidog run --helpで正確なレポーターフラグ(-r、--reporterなど)と出力オプションを確認し、それに合わせて例を調整してください。
トレンドグラフ付きでAzureの組み込みテストタブで結果を見たい場合は、CLIにJUnit XMLを出力させ、XMLを指すPublishTestResults@2タスクを追加します。これにより、単発のファイルだけでなく、ビルドごとのアサーション履歴が得られます。
ステップ6:ゲートを実体化する
パイプラインを設定するのと、それを強制するのとは異なります。デフォルトでは、Azure DevOpsに要求しない限り、失敗したビルドは誰もマージを止めることはありません。
mainブランチにブランチポリシーを設定します。
- リポジトリ、次にブランチに移動し、
mainを見つけてブランチポリシーを開きます。 - ビルド検証を追加し、パイプラインを選択します。
- これを必須に設定します。
これで、APIテストパイプラインが合格するまで、プルリクエストはmainにマージできなくなります。これが、実行されるテストと保護するテストの違いです。これをオンにするまでは、ダッシュボードがあるだけですが、オンにした後は、ゲートがあることになります。
現実的なデータ駆動型テストの例
単発のシナリオは明白な障害を捉えます。実際のAPIでは、多数の入力(有効なペイロード、エッジケース、500ではなく400を返すはずの不正なリクエストなど)で同じエンドポイントを検証する必要があります。
Apidogはデータ駆動型テストをサポートしています。CSVまたはJSONデータセットをシナリオに添付すると、各行ごとに一度実行され、行の値をリクエストとアサーションに置き換えます。例えば、ログインシナリオでは、有効なユーザー、間違ったパスワード、ロックされたアカウント、空のボディなど、それぞれが期待されるステータスコードを持つ行を実行できます。
パイプラインでは、コマンドの形式は何も変わりません。同じシナリオに対して引き続きapidog runを呼び出します。データセットはシナリオと一緒に移動するため、1回のCLI呼び出しですべての行がカバーされます。Apidogで新しいエッジケースを追加しても、次のパイプライン実行はYAMLを編集することなくそれを取り込みます。これが、テストロジックをパイプラインではなくツール内に保持することのメリットです。パイプラインは退屈なままですが、カバレッジは拡大します。
一般的な問題とその修正方法
エンドポイントが壊れているのにビルドが合格する。ほとんどの場合、終了コードの問題です。CLIが失敗時に非ゼロを返すこと(ステップ2)を確認し、それを飲み込んでいないことを確認してください。末尾の|| trueや、別のコマンドで終わるマルチコマンドスクリプトは失敗を隠蔽します。apidog runの呼び出しをスクリプトブロックの最後の意味のあるコマンドとして保持してください。
apidog: command not found。インストールステップが実行されなかったか、テストステップの後に実行されたか、またはエージェントのシェルが認識できないパスにインストールされた可能性があります。npm install -g apidog-cliが実行ステップの前に現れることを確認してください。一部のセルフホストエージェントでは、グローバルnpm binがPATHに含まれていない場合があります。その場合は、ローカルにインストールし、代わりにnpx apidog run ...を介して呼び出してください。
CIでは認証に失敗するが、ローカルでは動作する。シークレットがステップに到達していません。シークレット変数はenv:を介してマッピングする必要があります(ステップ4)。これらは自動的に注入されません。また、トークンが末尾の改行や引用符で貼り付けられていないかも確認してください。
テストが間違った環境にヒットする。-eの値が間違ったApidog環境を指しているか、環境のベースURLがまだlocalhostを参照しています。到達可能でCIセーフなURLに解決される専用のStaging環境を保持し、そのIDを-eで明示的にCLIに渡してください。
実行ごとに合否が不安定になる。通常は、共有される可変状態が原因です。レコードを作成するテストと、それに衝突する後続の実行です。シナリオを自己完結型にしてください。必要なものを作成し、アサートし、その後クリーンアップするか、実行ごとに一意の識別子を使用して、再実行が昨日のデータに干渉しないようにします。別のツールから移行する場合、NewmanなしでCIでAPIテストを実行する方法のパターンは、同じ分離の落とし穴をカバーしています。
基本を超えて
コアパイプラインが堅牢になったら、いくつかの拡張機能が役立ちます。
- 夜間実行をスケジュールする。
schedulesトリガーを追加して、午前2時にステージングに対してフルスイートを実行し、コードがプッシュされない日でもデータ変更やサードパーティAPIの変更によるずれを検出できるようにします。 - 高速スイートと低速スイートを分割する。各PRで迅速なフィードバックのために簡単なスモークシナリオを実行し、
mainへのマージで完全な回帰スイートを実行します。2つのパイプライン定義で、同じCLIを使用します。 - マトリックスで複数の環境をテストする。パイプラインマトリックスを使用して、同じシナリオをステージング環境とプリプロダクション環境に対して並行して実行し、それぞれに独自の環境IDを設定します。
- マージだけでなくデプロイもゲートする。APIテストステージをマルチステージパイプラインのデプロイステージの前に配置し、テストの失敗がマージだけでなくリリースも停止するようにします。
これらはいずれも、同じ基盤に対する小さな追加です。つまり、クリーンに終了するCLIと、終了コードを尊重するパイプラインです。
よくある質問
Azure PipelinesでAPIテストを実行するために、何かコードを書く必要がありますか?いいえ。Apidogでテストシナリオを視覚的に構築し、パイプラインは単一のCLIコマンドでそれらを実行します。「コード」はazure-pipelines.yml自体だけで、これはテストロジックではなく設定です。完全にスクリプトベースのテストを好む場合でもそうすることは可能ですが、このワークフローの目的はそれをスキップすることです。
既存のPostmanコレクションをAzure Pipelinesで代わりに実行できますか?はい、通常Newmanまたは同様のランナーを使用すれば可能です。オプションを検討している場合、ApidogはPostmanコレクションを直接インポートできるため、既存のテストを取り込み、別のツールチェーンを維持することなく同じCLIで実行できます。NewmanなしでCIでAPIテストを実行する方法で比較を確認してください。
テストはどこを指すべきですか?ステージングですか、それとも本番ですか?ほとんどの場合、ステージングまたはブランチごとのプレビュー環境です。本番環境に対して書き込みの多いテストを実行すると、実際のデータが汚染され、実際の副作用を引き起こす可能性があります。CI用に安全なベースURLを持つ専用のApidog環境を保持し、そのIDを-eでCLIに渡してください。
パイプラインはどのようにテストの失敗を知るのですか?終了コードを通してです。apidog runはすべてのアサーションが成功した場合は0を返し、いずれかが失敗した場合はゼロ以外のコードを返します。Azure Pipelinesは非ゼロ終了時にスクリプトタスクを失敗させ、それがビルドの失敗につながります。一度ローカルでecho $?で確認し、ゲートを信頼できるようにしてください。
これはAzure DevOps Classic (UI) パイプラインでも、YAMLだけでなく機能しますか?はい。同じ手順が適用されます。「Nodeを使用」タスク、npm install -g apidog-cliを実行するコマンドラインタスク、そしてapidog run ...を実行する別のコマンドラインタスクを追加します。YAMLはリポジトリに保存され、バージョン管理されるため推奨されますが、ランナーはステップがどのように定義されているかを気にしません。
Microsoftホスト型エージェントの代わりにセルフホスト型エージェントを使用できますか?はい。セルフホスト型エージェントも同様に機能します。Node.jsがインストールされており、グローバルnpm binがエージェントのPATHにあるか、またはnpxを介してCLIを呼び出すことを確認してください。セルフホスト型エージェントは、ステージングAPIがプライベートネットワーク内からのみ到達可能な場合に役立ちます。
まとめ
CIビルドがグリーンであることは、コードがコンパイルされただけでなく、APIが実際に機能していることを意味するべきです。Azure Pipelinesでそれに到達するには、4つのステップがあります。Apidogで実際のテストシナリオを設計し、Apidog CLIでヘッドレスに実行し、終了コードでビルドステータスを決定し、マージする前にビルドが合格することを必須とします。このループが稼働すれば、すべてのプッシュが、最も注意深いチームメイトが与えるであろう精査を、自動的に、毎回受けます。
これが保守可能であり続ける理由は、分離にあります。テストロジックはApidogに存在し、API仕様に近く、拡張が容易です。パイプラインは薄いラッパーのままです。インストール、実行、レポート。APIが成長しても、ツール内でシナリオとデータ行を追加するだけで、パイプラインは編集なしでその役割を果たし続けます。
設定準備はできましたか?Apidogをダウンロードし、テストシナリオを構築し、CLI実行コマンドを取得して、azure-pipelines.ymlにドロップしてください。次の回帰は顧客ではなくマシンによって検出されます。
ボタン
