ラップトップではAPIがすべてのテストに合格しました。しかし、チームメイトがフィールド名を変更するブランチをマージすると、本番環境でモバイルクライアントがクラッシュし始めるまで誰もそれに気づきません。手動テストではスイートを再実行しなかったため見落とされました。これこそ、継続的インテグレーションが解決するために構築されたギャップであり、TeamCityはそのギャップを埋めるための最も強力なツールの1つです。
JetBrainsのCI/CDサーバーであるTeamCityは、コードがコミットされるたびにビルドパイプラインを実行します。ボタンをクリックすることなく、コンパイル、テスト、パッケージ化、デプロイが可能です。チームがしばしばスキップするのは、実際のAPIテストをそのパイプラインに組み込むことです。彼らはユニットテストを行い、ビルドがコンパイルされることをテストし、APIを信頼に基づいて出荷します。フィールド名の変更、エッジケースでの500エラー、壊れた認証フローなど、人間がエンドポイントにアクセスするまで、それらは何も表示されません。
このガイドでは、TeamCity内で自動APIテストを最初から最後まで実行する方法を説明します。Apidogでテストを設計・検証し、Apidog CLIを通じてヘッドレスでTeamCityのビルドステップとして実行します。これにより、APIが正常に動作しなくなった瞬間にビルドが失敗するパイプラインが構築され、不正なレスポンスがユーザーに届く前に問題を特定できます。
構築するもの
最終的には以下のものが手に入ります。
- Gitリポジトリに接続されたTeamCityプロジェクト
- プッシュごとに起動するVCSトリガーを備えたビルド構成
- Apidog CLIを通じてAPIテストスイートを実行するビルドステップ
- TeamCityのテストタブに表示されるパース済みテスト結果
- エンドポイントが壊れたときに赤色になり、マージをブロックするビルド
このパターンは、小規模な内部サービスでも、数百のエンドポイントを持つ公開APIでも機能します。パイプラインコードを編集するのではなく、Apidogでテストシナリオを追加することで拡張できます。

APIテストがローカルマシンだけでなくTeamCityに属する理由
ローカルテストには致命的な欠陥があります。それは、誰かがテストを実行することを覚えているかどうかに依存するということです。CIは人間をループから排除します。すべてのコミットは、同じ環境で、同じアサーションを使用して、同じスイートをトリガーします。ビルドエージェントが定義された正確なステップを実行するため、「私のマシンでは動くのに」という状況は発生しません。

TeamCityは、いくつかの具体的な理由からこれに適しています。
- ビルドチェーン。APIテストステップをデプロイ-to-ステージングステップに依存させることができるため、テストは常に新しくデプロイされたビルドに対して実行され、古いビルドに対して実行されることはありません。
- テスト履歴。TeamCityは、数百のビルドにわたってどのテストが成功し、失敗したかを追跡します。テストが不安定になり始めたとき、どのコミットが原因で発生したかを正確に確認できます。
- 調査とミュート。不安定なエンドポイントはミュートされ、担当者に割り当てられることで、全員のマージをブロックするのを防ぐことができます。
- エージェントプール。重いスイートは専用のエージェントで実行されるため、コンパイルビルドの速度を低下させません。
注意点として、TeamCityはAPIを呼び出したり、レスポンスをチェックしたりする方法を知りません。TeamCityは指定されたコマンドを実行するだけです。したがって、本当の作業は、APIスイート全体を実行し、何らかの問題が発生した場合に非ゼロのコードで終了する単一のコマンドを作成することです。そこにテスト設計の重要性があります。
ステップ1:ApidogでAPIテストを設計・検証する
TeamCityを触る前に、実際に無人で実行できるテストが必要です。JSONレスポンスを目視で確認する必要があるテストはCIでは役に立ちません。すべてのチェックは、マシンが評価できるアサーションである必要があります。ステータスコードが200であること、idフィールドが数値であること、レスポンスが800ms未満で返されたことなどです。
Apidogはまさにこのために構築されています。リクエストを設計し、レスポンスを自動的に検証するAPIアサーションをアタッチします。ステータスコード、JSONスキーマへの準拠、特定のフィールド値、レスポンス時間などです。リクエストをシナリオとしてチェーン化できるため、ログイン呼び出しの出力からトークンを次のリクエストに渡すことができます。一般的なケースではスクリプトは不要で、必要な場合には完全なスクリプト機能が利用できます。
eコマースAPIの現実的なシナリオは次のようになります。
- テスト認証情報で
/auth/loginにPOSTリクエストを送信し、200であることをアサートし、ベアラートークンを変数として抽出します。 - そのトークンで
/products?category=booksにGETリクエストを送信し、200であることをアサートし、レスポンスが配列であることをアサートし、すべてのアイテムのpriceが0より大きいことをアサートします。 - 商品IDで
/cart/itemsにPOSTリクエストを送信し、201であることをアサートし、返されたカートの合計が商品価格と一致することをアサートします。 /cartにGETリクエストを送信し、アイテム数が1であることをアサートします。
各ステップには、それ自体で成功または失敗するアサーションがあります。まずApidog内でシナリオを実行し、ステージング環境に対して正常に動作することを確認してください。手動で実行しても合格しない場合、CIでは決して合格しません。関連するシナリオをテストスイートにグループ化することで、シナリオごとにではなく、単一のコマンドで全体を実行できます。
この方法でテストを構築する利点は、手動デバッグに使用するのと同じシナリオがCIスイートになることです。探索用のGUIと自動化用のコードという2つの並行したテストセットを維持する必要はありません。これは単一の真実源です。もしあなたがREST Assuredのようなコードファーストのフレームワークから移行してきたのであれば、これは最も時間を節約できる部分です。各エンドポイントのために定型的なリクエスト/アサーションコードを書き直す必要がなくなります。
一緒に構築したい場合は、Apidogをダウンロードしてください。無料で始められ、CLIは同じツールチェーンの一部です。
ステップ2:まずApidog CLIをローカルで実行する
CI内で新しいコマンドを最初にデバッグしてはいけません。CIサーバーのフィードバックループは過酷です。プッシュし、エージェントを待ち、ログを読み、1文字修正し、再度プッシュします。コマンドがマシンで動作することを確認してから、動作するバージョンをTeamCityにコピーしてください。
Apidog CLIはNode.jsで動作するため、npmでグローバルにインストールします。
npm install -g apidog-cli
インストールされたことを確認します。
apidog --version
次にテストシナリオを実行します。CLIは、アクセスークンで認証されたプロジェクトIDを参照するか、ローカルにエクスポートされたファイルから、Apidogプロジェクトから直接シナリオまたはスイートを実行できます。オンラインアプローチは、テストを単一の真実源として維持します。チームがApidogで編集したものがCIで実行され、エクスポートの手順を忘れることもありません。
Apidogアカウント設定からアクセストークンを生成し、次に実行します。
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-e "$APIDOG_ENV_ID" \
-r cli,html,junit
ここで注目すべき点がいくつかあります。
--access-tokenは実行を認証します。このようにインラインで渡すか、apidog login --with-tokenで一度ログインします。-eはどの環境に対して実行するかを選択します。ステージング、本番読み取り専用、Apidogで定義したものなどです。このIDを切り替えることで、同じテストを異なるベースURLにポイントできます。-rはレポーターを選択します。cliはコンソールに人間が読める出力を表示し、htmlはブラウズ可能なレポートを生成します。JUnit形式のレポートは、TeamCityが個々のテスト結果を解析して表示できるようにするものです。
実行が終了すると、すべてが合格した場合はCLIは0で終了し、いずれかのアサーションが失敗した場合は非ゼロで終了します。この終了コードがCIにおけるすべてです。非ゼロの終了は、TeamCityにビルドを失敗としてマークするよう指示します。
多くの入力に対して実行する必要があるテストの場合、CLIはデータ駆動型実行をサポートしています。CSVまたはJSONファイルを指定すると、行ごとにシナリオが繰り返されます。
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-d test-data/checkout-cases.csv \
-r cli,junit
これにより、100個のシナリオを作成することなく、100個の商品IDや無効なペイロードの表をテストできます。各行は独自の反復となり、独自の合格/失敗結果を持ちます。
ローカルで緑色の出力が表示されたら、信頼できるコマンドが手に入ったことになります。それをコピーしてください。その正確なコマンドがTeamCityに入力されます。
ステップ3:TeamCityをリポジトリに接続する
次にTeamCityに切り替えます。このステップの目標は、TeamCityにプロジェクトを与え、コードを指し示し、すべてのプッシュでビルドをトリガーさせることです。
TeamCityを初めて実行する場合、最も簡単な方法は公式のDockerイメージです。数分で動作するサーバーが手に入ります。
docker run -d --name teamcity-server \
-v ~/teamcity/datadir:/data/teamcity_server/datadir \
-v ~/teamcity/logs:/opt/teamcity/logs \
-p 8111:8111 \
jetbrains/teamcity-server
http://localhost:8111を開き、初回セットアップ(データベースの選択、管理者アカウント)を完了すると、ダッシュボードに移動します。本番環境のセットアップでは適切な外部データベースと専用のビルドエージェントを使用しますが、このガイドに従うにはバンドルされたエージェントで十分です。
プロジェクトを作成します。
- 管理に移動し、プロジェクトを作成を選択します。
- リポジトリURLから選択し、Gitリモート(HTTPSまたはSSH)を貼り付けます。
- リポジトリがプライベートな場合は、デプロイキーまたはパーソナルアクセストークンなどの資格情報を追加します。
- TeamCityはリポジトリをスキャンし、ビルドステップを自動検出する必要があります。これを許可することもできますが、APIテストの場合は、次のセクションで自分でステップを設定する方がクリーンです。
TeamCityはVCSルート(リポジトリへの接続)とビルド構成(実行されるステップのセット)を作成します。VCSルートが設定されたら、ビルドが自動的に起動するようにトリガーを設定します。
- ビルド構成を開き、トリガーに移動します。
- VCSトリガーを追加します。
- 監視対象のブランチへのすべての変更がビルドをキューに入れるように、デフォルトのルールを残します。
ここから、リポジトリへのすべてのプッシュがビルドを起動します。現時点ではそのビルドは何も有用なことをしません。次のステップでAPIテストコマンドを与えます。
ステップ4:Apidog CLIをビルドステップとして追加する
これがセットアップの中核です。エージェントにCLIをインストールし、スイートを実行するビルドステップを追加します。
ビルド構成でビルドステップを開き、タイプ「コマンドライン」の新しいステップを追加します。カスタムスクリプトを選択して貼り付けます。
#!/bin/bash
set -e
# Install the Apidog CLI on the build agent
npm install -g apidog-cli
# Run the API test suite and emit a JUnit report for TeamCity
apidog run \
--access-token "%env.APIDOG_ACCESS_TOKEN%" \
-e "%env.APIDOG_ENV_ID%" \
-r cli,junit \
--out-dir reports
これはローカルで確認したのと同じコマンドですが、CI向けに2つの変更が加えられています。まず、set -eはエラーが発生するとスクリプトを中止します。次に、シークレットはハードコーディングするのではなく、TeamCityパラメータ(%env.APIDOG_ACCESS_TOKEN%)として参照されます。これらは次に定義します。
ビルドエージェントにNode.jsがまだインストールされていない場合は、チェーンの早い段階でインストールするか、Nodeを含むエージェントイメージを使用してください。公式のTeamCityエージェントDockerイメージとほとんどのクラウドエージェントプールにはNodeが同梱されています。また、ステップをnode:20のようなDockerイメージ内で実行するように設定することで、ステップ全体をNodeコンテナ内で実行することもできます。
一つ重要な点があります。CLIはAPIがデプロイされ、到達可能になった後に実行する必要があります。TeamCityがステージングにデプロイしたばかりのサービスをテストする場合、スナップショット依存関係またはビルドチェーンを使用して、テストビルドをデプロイビルドに依存させます。これにより、テストは常にこのコミットで生成されたAPIバージョンをテストし、前のバージョンをテストしないことが保証されます。
ステップ5:TeamCityパラメータとしてシークレットを保存する
アクセストークンは資格情報です。ビルドスクリプト、リポジトリ、ビルドログに属するべきではありません。TeamCityにはこれのためのファーストクラスの場所があります。
- ビルド構成(または、複数の設定で共有するために親プロジェクト)で、「パラメータ」を開きます。
env.APIDOG_ACCESS_TOKENという名前の新しいパラメータを追加します。- そのSpecをPasswordに設定します。これにより、UIで値がマスクされ、ビルドログから消去されます。
- Apidogアクセストークンを値として貼り付けます。
- 同様に
env.APIDOG_ENV_IDを環境IDで追加します(これはシークレットではありませんが、パラメータとして保持することで、スクリプトを編集せずに環境を変更できます)。
これらをビルド構成レベルではなくプロジェクトレベルで定義すると、そのプロジェクト下のすべてのAPIテストビルドがそれらを継承します。トークンを一度ローテーションすれば、すべてのパイプラインが新しい値を取得します。
パスワードパラメータは、TeamCityに安全に保存されるトークンと、チーム全体が読めるログファイルに漏洩するトークンの違いです。データベースのパスワードを扱うのと同じように扱ってください。
ステップ6:TeamCityのテストタブにテスト結果を表示する
赤色になるビルドは、何かが壊れたことを示します。どのテストが壊れたかを示すビルドは、どこを見るべきかを教えてくれます。それがJUnitレポートが提供するものです。

-r junitレポーターは、JUnit形式のXMLファイルを書き込みます。これは、TeamCityがネイティブに読み取る標準のCIテスト結果形式です。XMLレポート処理ビルド機能を使用して、そのファイルをTeamCityに指定します。
- ビルド構成でビルドヘッダーを開きます。
- XMLレポート処理を追加します。
- レポートタイプをAnt JUnitに設定します。
- 出力に一致するように監視パスを設定します。例:
reports/*.xml。
ビルドを実行します。それを開き、「テスト」タブをクリックします。各シナリオとアサーションが、合格/失敗ステータスとタイミングとともに個別のテストとして表示されます。テストが失敗すると、TeamCityはインラインで失敗メッセージを表示し、それに関連するコミットにリンクし、将来のビルドで追跡します。同じテストが2回連続で失敗すると、TeamCityはそれを不安定なものではなく、新しい失敗としてフラグ付けできます。
これは、以前にJUnit出力を選択したことに対する報酬です。これがない場合、失敗は1つの赤いビルドとコンソールテキストの壁です。これがある場合、「APIビルドが壊れている」が「コミットa3f9c2でカート合計アサーションが失敗し始めた」という、構造化された検索可能なテスト履歴が得られます。
ステップ7:ビルドを失敗させ、マージをブロックする
これらすべてを行う目的は、悪いコードがマージされるのを阻止することです。それを実現するには2つのことがあります。
まず、終了コードです。Apidog CLIはいずれかのアサーションが失敗すると非ゼロで終了し、スクリプトはset -eを使用するため、失敗したテストはビルドステップを失敗させ、それがビルドを失敗させます。追加の設定は必要ありません。APIテストが赤色になれば、デフォルトでビルドも赤色になります。
次に、マージゲートです。チームがプルリクエストまたはマージリクエストで作業している場合、マージする前にTeamCityチェックを必須にするようにGitホスト(GitHub、GitLab、Bitbucket)を設定します。TeamCityは、コミットステータス発行元ビルド機能を通じて、ビルドステータスをコミットに報告します。
- コミットステータス発行元ビルド機能を追加します。
- VCSホスティングプロバイダを選択します。
- TeamCityがステータスを投稿できるように、アクセストークンを追加します。
これで、貢献者がPRを開くと、TeamCityがそのブランチに対してAPIスイートを実行し、スイートが緑色になるまでマージボタンは無効のままになります。このガイドの冒頭で述べたフィールド名変更のシナリオは、メインに到達する前に、ブランチでここで捕捉されます。
現実的な完全なパイプライン
これらを組み合わせると、APIテストパイプラインの動作するビルド構成は次のようになります。
- メインブランチとPRブランチにVCSトリガーが設定された、リポジトリを指すVCSルート。
- ビルドステップ1:サービスをステージング環境にデプロイする(またはエージェント上のDockerコンテナで起動する)。
- ビルドステップ2:ステップ4のApidog CLIコマンドを、そのステージング環境に対してスイートを実行する。
- ビルドに含まれる機能:
reports/*.xmlを読み取るXMLレポート処理。 - ビルドに含まれる機能:Gitホストにステータスを報告するコミットステータス発行元。
- パラメータ:
env.APIDOG_ACCESS_TOKEN(パスワード)とenv.APIDOG_ENV_ID。
すべてのCI構成をバージョン管理しているチームの場合、TeamCityはUIでクリックする代わりに、Kotlin DSL(.teamcity/settings.kts)でこれらすべてを定義し、リポジトリにコミットすることをサポートしています。ビルドステップはどちらの方法でも同じapidog runコマンドです。DSLは構成をコードとして記述するため、他のすべてと同様にレビューされ、バージョン管理されます。

スイートは毎回のプッシュだけでなく、それ以上にも実行できます。スケジュールトリガーを追加して、毎晩ステージングに対して完全な回帰スイートを実行することで、コミット間のドリフト(変更されたサードパーティの依存関係、奇妙な状態になったデータベースなど)を捕捉できます。夜間のAPI実行は安価な保険であり、翌朝の最初のコミットが前日の壊れた環境を引き継ぐことを防ぎます。
他のCIプラットフォームとの比較
ここでのパターンはポータブルです。テストを実行するコマンド(アクセストークンとJUnitレポーターを伴うapidog run)は、どのCIサーバーがそれを呼び出しても同じです。変更されるのはラッパーだけです。
- GitHub Actionsでは、同じコマンドをワークフローYAMLステップに配置します。これはGitHub ActionsでAPIテストを自動化する方法で説明しています。
- Jenkinsでは、
Jenkinsfileステージに配置します。JenkinsとApidog自動テストを統合してCI/CDを行う方法を参照してください。 - あらゆるプラットフォームでの広範な戦略は、CI/CDでAPIテストを自動化する方法で説明されています。
CIサーバーをまだ選択中の場合、最適なCI/CDツールの比較では、TeamCityが他の選択肢と比較してどの位置にあるかを分析しています。TeamCityの強みは、ビルドチェーン、きめ細かなテスト履歴、およびKotlin DSLです。JetBrainsエコシステムを既に利用しているチームや、複雑なマルチステージパイプラインを実行しているチームにとって強力な選択肢です。
一般的な問題と解決策
ビルドがapidogコマンドを見つけられません。 Node.jsがエージェントにインストールされていないか、グローバルnpm binディレクトリがエージェントのPATHにありません。チェーンの早い段階でNodeのインストールステップを追加するか、node:20 Dockerイメージ内でステップを実行してください。
テストはローカルでは合格するのに、CIでは接続エラーで失敗します。 ビルドエージェントがAPIにアクセスできません。ラップトップのVPNで解決されるステージングURLは、クラウドエージェントからは到達できない場合があります。-eで選択した環境が、エージェントが実際に到達できるホストを指していること、および必要なネットワークアクセスやファイアウォールルールがエージェントをカバーしていることを確認してください。
認証がCIでのみ失敗します。 パスワードパラメータがスクリプトが参照する通りに正確にスペルされていること、およびトークンが期限切れになっていないことを確認してください。よくある間違いは、スクリプトが%env.APIDOG_ACCESS_TOKEN%と読み込むのに、APIDOG_ACCESS_TOKENを定義していることです。env.プレフィックスは重要です。
テストが不安定です。同じコードで合格したり失敗したりします。 通常、タイミングまたはデータ順序の問題です。Apidogの応答時間アサーションを使用して遅いエンドポイントを特定し、各シナリオが独自のデータをセットアップおよびティアダウンするようにして、実行が互いの残り物に依存しないようにします。TeamCityのミュートおよび調査機能を使用すると、不安定なテストを隔離して、根本原因を修正している間、誰もがブロックされないようにすることができます。
ビルドが実行されたにもかかわらず、テストタブが空です。 XMLレポート処理パスが、CLIがレポートを書き込んだ場所と一致していません。コマンドの--out-dirと、ビルド機能の監視パスが同じ場所を指していることを確認してください。
FAQ
TeamCityでAPIテストを実行するためにコードを書く必要がありますか? いいえ。Apidogでアサーションを使って視覚的にテストを設計し、TeamCityの「コード」はコマンドラインビルドステップの1行のapidog runコマンドだけです。これが、REST Assuredのようなコードファーストのアプローチとは主な違いで、そこではすべてのエンドポイントに手書きのリクエストおよびアサーションコードが必要です。
異なる環境に対してテストを実行できますか? はい。Apidogで各環境(ステージング、プリプロダクション、本番読み取り専用)を定義し、-e環境IDパラメータを変更することで、CIで実行する環境を切り替えます。同じテストは、異なるベースURLを指すことで、どの環境に対しても実行できます。
TeamCityでアクセストークンを安全に保つにはどうすればよいですか? パスワード指定のTeamCityパラメータとして保存します。これにより、UIでマスクされ、ビルドログから消去されます。ビルドスクリプトにハードコードしたり、リポジトリにコミットしたりしないでください。すべてのパイプラインで一度ローテーションできるように、プロジェクトレベルで定義してください。
失敗したAPIテストは実際にマージをブロックしますか? はい、2つの要素が揃っていれば可能です。Apidog CLIはいずれかのアサーションが失敗すると非ゼロで終了し、これによりTeamCityのビルドが失敗します。コミットステータス発行元ビルド機能を追加し、Gitホストのブランチ保護ルールでチェックを必須にすることで、スイートが合格するまでマージボタンは無効のままになります。
オンラインでのテスト実行とエクスポートファイルからのテスト実行の違いは何ですか? プロジェクトIDとアクセストークンを使用してオンラインで実行する場合、Apidogのテストが単一の真実源となります。チームが編集したものがCIで実行されます。エクスポートされたファイルから実行する場合、テストはリポジトリにコミットされたバージョンに固定されます。オンラインの方が同期を保つのが簡単です。エクスポートされたテストはコードとともに移動します。ほとんどのチームはオンラインで始めます。
毎回のプッシュではなく、スケジュールで完全な回帰スイートを実行できますか? はい。ビルド構成にスケジュールトリガーを追加して、毎晩(または毎時間)ステージングに対して実行します。多くのチームは、毎回のプッシュで高速なスモークスイートを実行し、夜間スケジュールで完全な回帰スイートを実行することで、迅速なフィードバックと深いカバレッジが同じ時間で競合しないようにしています。
まとめ
すべてのコミットでAPIテストを実行するTeamCityパイプラインは、壊れたエンドポイントの経済性を変えます。顧客がバグを見つける代わりに、ビルドがバグを見つけます。マージ前のブランチ上で、正確な失敗アサーションと、それが発生したコミットがテストタブに表示されます。
セットアップは3つの可動部分に集約されます。Apidogで構築する実際のアサーションを持つテスト、ヘッドレスで実行され、失敗時に非ゼロで終了する単一のapidog runコマンド、そしてそのコマンドを実行し、JUnit結果を解析し、Gitホストにステータスを報告するTeamCityビルド構成です。一度設定すれば、パイプラインコードに触れることなく、Apidogでシナリオを追加することでカバレッジを維持できます。
Apidogをダウンロードして最初のテストスイートを設計し、CLIコマンドをローカルで検証してから、TeamCityに組み込んでください。その時点から、APIは、誰かが実行することを覚えていようがいまいと、すべてのコミットで同じ方法でテストされるようになります。
