Amazon Web Services ブログ
Kiro で OpenAPI/Swagger 仕様から数秒でテストスイートを生成する
本記事は 2026 年 6 月 25 日に公開された Sumitha AP、Rajdeep Mukherjee による “From OpenAPI/Swagger specifications to test suite in seconds with Kiro” を翻訳したものです。
API は現代のアプリケーションの基盤です。チームが REST API を構築し改良していく中で、網羅的なテストカバレッジを維持することは継続的な課題となります。OpenAPI/Swagger 仕様は、API がどう振る舞うべきかを的確に記述します。エンドポイント、リクエストの形式、レスポンスのスキーマ、ステータスコードなどです。しかし、それらが実際に機能することを証明するものではありません。
そのギャップを埋める作業は、伝統的に開発者の肩にかかってきました。仕様を読み、各エンドポイントをテストケースに落とし込み、正常系とエッジケースを考慮し、テストランナーを組み立て、依存関係をモックし、結果を意味のある形で見せるためのレポート機能を構築します。中規模の API、例えばエンドポイントが 40 個あるとすると、製品コードを 1 行も書く前に 1 週間分の作業が必要です。しかも仕様が安定していることが前提ですが、実際にはほとんど安定しません。
根本的な課題は、API 仕様とそれに対応するテストスイートが独立して保守されていることです。時間が経つにつれ、両者は必然的に乖離していきます。リリース時に書かれたテストはエンドポイントの変更とともに陳腐化し、新しいエンドポイントはテストカバレッジを伴わずにリリースされていきます。
OpenAPI Generator のようなツールは仕様からテストのスキャフォルディングを生成できますが、通常は開発者自身が埋めるためのスタブを提供するだけです。Kiro は別のアプローチを取り、仕様をテスト生成の信頼できる情報源として扱います。OpenAPI/Swagger ファイルを入力すると、Kiro は動作するテストスイート、エンドポイントカバレッジ、エッジケース、スキーマ検証、レポート用スキャフォルディングを、テストファイルをセットアップする時間と同じくらいで生成します。さらに、Kiro は再生成を素早く低コストで行えるようにすることで、テストを仕様と同期させるコストを下げ、フックによってドリフトを早期に検出できます。本記事では、それがどのように機能し、何が生成されるのかを詳しく見ていきます。
Swagger と OpenAPI 仕様
Swagger は、構造化された JSON を使って REST API をドキュメント化する手段として作られました。どんなエンドポイントがあるか、各エンドポイントがどのパラメータを受け取るか、成功時に何を返すか、問題が起きたときに何を返すか、といった語彙を定義します。
最小限の OpenAPI ドキュメントは、各エンドポイントについて、URL パスと HTTP メソッド、受け取るパラメータ(型、位置(location)、必須/任意)、成功時のレスポンススキーマ、ありうるエラーレスポンスとそのコードを指定します。
# openapi.yaml: マシン可読な API の契約
openapi: "3.0.0"
paths:
/pet/{petId}:
get:
summary: "Find pet by ID"
parameters:
- name: petId
in: path
required: true
schema: { type: integer }
responses:
"200":
content:
application/json:
schema: { $ref: "#/components/schemas/Pet" }
"404":
description: "Pet not found"
OpenAPI ドキュメントは単なるドキュメント以上のものです。REST API のインターフェースを完全に記述する構造化された定義ファイル(JSON または YAML)です。API の提供者と利用者の間の契約として機能し、マシン可読であるため、適切なツールがそれを解析し、推論し、実際の成果物を生成できます。この点は、以降の議論すべてに関わる重要なポイントです。
本記事では、エージェント駆動の開発システムである Kiro を使って、Swagger API 仕様から直接、モックサーバー・設定トグル・HTML テストレポートまで含む実行可能な Node.js テストスイートを自動生成する方法を示します。
既存ツールが力不足な理由
これまでに OpenAPI 仕様を扱ったことがあれば、OpenAPI Generator や Swagger Codegen に出会ったことがあるでしょう。背景として、OpenAPI Generator はガバナンスの違いから 2018 年に Swagger Codegen からフォークされました。両者は似た目標を持ちますが、独立して保守されており、リリース頻度や機能セットも異なります。どちらも仕様ファイルを受け取り、選択した言語のクライアントライブラリ、サーバースタブ、SDK コードを生成するオープンソースツールです。HTTP のボイラープレートを削減するには優れていますが、API の振る舞いを検証する目的では設計されていません。テスト生成に使おうとすると、通常はアサーションが最低限のメソッドスタブ、限定的なモック、わずかなスキーマ検証しか得られません。もっとも、具体的な出力は使用する言語、テンプレート、設定によって異なります。テストはコンパイルされ実行はされるかもしれませんが、エッジケース、エラーハンドリング、スキーマの契約を意味のある形でカバーしているとは限りません。
これは見た目以上に深刻な問題です。アサーションのないテストでも CI ではパスし、カバレッジにはカウントされます。しかし実際にはステータスコード、レスポンスの形、エラーケースをチェックしていません。ビルドは成功し、カバレッジ数値も高いのに、400 が 500 として返されているといった特定のバグが見過ごされるということが起こり得ます。
Kiro はこの問題に異なるアプローチを取ります。仕様をテンプレート化するのではなく、仕様を推論します。enum の値を現実的なペイロードに解決し、実際のスキーマの契約に紐づいたアサーションを生成し、仕様で定義された振る舞いを反映したモックサーバーを作り出します。出力されるのは後で埋めるためのスキャフォルディングではなく、意味のあるカバレッジを持つ実行可能なテストです。
|
機能 |
OpenAPI Generator |
Kiro |
|---|---|---|
|
アサーション付きの実行可能なテストを生成 |
◐ 限定的(テンプレート依存) |
✓ あり |
|
仕様に対応するモックサーバーを構築 |
✗ なし |
✓ あり |
|
スキーマから現実的なペイロードを推論 |
◐ 部分的 |
✓ enum の解決を含む |
|
チームのコーディング規約に適合 |
◐ カスタムテンプレート |
✓ ステアリングファイル経由 |
|
仕様のドリフトに応じて CI で再生成 |
✗ 手動 |
✓ ヘッドレスモード |
|
自然言語の意図を理解 |
✗ なし |
✓ あり |
機能比較: テンプレートベースのジェネレーター vs. Kiro のエージェント駆動アプローチ。
テンプレートベースのアプローチでは、特定の種類の問題が検出されないままになり得ます。例えば 400 エラーが 500 として返されたり、認証エンドポイントが不正な形式のトークンを受け入れたりするケースです。とくに、生成されたテストが実際にはエンドポイントへの呼び出しを行わず、レスポンスの検証もしない場合に顕著です。これらのツールは主にコード生成のために設計されており、振る舞いの検証のためのものではありません。一方で Kiro は、各エンドポイントを実際に呼び出し、レスポンスが仕様で定義されたものと一致するかを検証するテストを生成します。これにより、API の実際の準拠状況についてより信頼できるシグナルが得られます。
ソリューション概要
本ソリューションでは、サンプルの PetStore の Swagger/OpenAPI 仕様 URL を入力として受け取り、Kiro を使って完全に機能するテストプロジェクトを生成します。生成されるプロジェクトには以下のコンポーネントが含まれます。
-
axios を使用したテストクライアント:Swagger 仕様で定義されたすべてのエンドポイントをカバーする HTTP テスト。GET、POST、PUT、DELETE 操作と、それに応じたリクエストペイロードおよびレスポンスアサーションを含みます。
-
Express のモックサーバー:API をシミュレートするローカルサーバー。各エンドポイントに対して現実的なレスポンスを返すため、ネットワークアクセスや実サービスへの依存なしにテストを実行できます。
-
設定トグル:同じテストスイートをモックサーバー(ローカル開発用)または実 API(統合テスト用)に対して実行できる簡単なスイッチ。
-
HTML テストレポート:各テストケースの合否と詳細なエラー情報を表示する、スタイル付きで共有可能なレポート。CI/CD パイプラインやプルリクエストのレビューに適しています。
-
外部テストフレームワークゼロ:テストは素の Node.js と軽量なカスタムランナーで動作し、フレームワークのバージョン競合をなくし、セットアップの手間を減らします。
前提条件
このウォークスルーを進めるには、以下が必要です。
-
Node.js
-
Swagger/OpenAPI 仕様の URL(例として Petstore API を使用します)
Kiro でテストスイートを生成する
それでは、Petstore の Swagger 仕様から完全なテストスイートを生成しましょう。テスト生成のルールをすべてプロンプトに埋め込むのではなく、Kiro のステアリングファイルを使用します。ステアリングファイルは「.kiro/steering/」に配置され、ワークスペース内のすべてのプロンプトで Kiro が従う永続的な指示を提供します。これにより、テスト生成の基準を一度定義しておけば、すべてのプロンプトでその恩恵を受けられます。本ブログでは このサンプルステアリングファイルを使用しました。チームのニーズや基準に合わせてカスタマイズしてください。
※ この図は GIF 形式に変換しているため画質が粗くなっています。鮮明な動画は原文記事をご参照ください。
サンプルプロンプト
Kiro の vibe モードで使用するサンプルプロンプトを示します。
Generate a Node.js test suite from https://petstore.swagger.io/index.html using axios, Express for mocking, and no external test frameworks
Kiro は Swagger 仕様を読み込み、すべてのエンドポイントを解析し、プロジェクト全体を生成します。
※ この図は GIF 形式に変換しているため画質が粗くなっています。鮮明な動画は原文記事をご参照ください。
生成されたプロジェクト構造を確認する
Kiro は以下のような構造のプロジェクトを生成します。
-
config.js:設定トグルを含みます。
useMockServer: trueに設定するとローカルの Express モックサーバーに対してテストを実行し、useMockServer: falseに設定すると実際の Petstore API を対象にします。 -
mock-server/server.js:Petstore のすべてのエンドポイントに対するルートハンドラを持つ Express アプリケーション。各ハンドラは、Swagger 仕様で定義されたスキーマに一致する現実的なレスポンスデータを返します。
-
test/:API リソース(pet、store、user)ごとに整理された個別のテストファイル。各ファイルには、そのリソースのすべての操作に対するテストが含まれ、レスポンスのステータスコードとペイロード構造に対するアサーションがあります。
-
test-runner.js:軽量な素の Node.js テストランナー。すべてのテストファイルを検出して実行し、合否のカウントを追跡し、エラーの詳細を取得します。
Kiro がどのように仕様を解析するかを理解する
Kiro は汎用的なテストスタブを生成するだけではありません。Swagger 仕様とステアリングファイルの指示を読み込んで、次のことを行います。
-
すべてのエンドポイントと HTTP メソッドを識別する:Petstore API の場合、POST /pet、GET /pet/{petId}、PUT /pet、DELETE /pet/{petId}、GET /store/inventory、POST /user/createWithList などの操作が含まれます。
-
スキーマ定義からリクエストペイロードを推論する:POST および PUT 操作について、Kiro は仕様内のモデル定義に基づいて有効なリクエストボディを構築します(例えば、id、name、category、photoUrls、tags、status フィールドを持つ Pet オブジェクト)。
-
期待されるレスポンスコードに基づいて検証コードを生成する:各テストは、仕様のレスポンス定義で定められた正しい HTTP ステータスコード(
200、201、404、405)を検証します。 -
対応するモックサーバーのルートを作成する:仕様内のすべてのエンドポイントに対して、定義されたレスポンススキーマに合致したデータを返す Express ルートハンドラが生成されます。
テストを実行する
モックサーバーに対して実行する
ローカルのモックサーバーに対してテストスイートを実行するには、チャットインターフェースで次のプロンプトを入力します。
Run the tests with the mock server
以下のような結果が表示されるはずです。
テストランナーはモックの Express サーバーを起動し、すべてのテストケースを実行し、レポートを生成します。生成された test-report.md をブラウザで開いて結果を確認してください。
テストの品質と分類
生成されたテストスイートには、Petstore の Swagger 仕様で定義されたすべてのエンドポイントをカバーするテストケースが含まれています。これらはユニットテストではなく統合テストです。各テストは axios 経由で実行中の Express サーバーに対して実際の HTTP リクエストを送り、TCP トランスポート、ミドルウェアのパース、ルートマッチング、ハンドラのロジック、状態の変化、JSON シリアライズといったスタック全体を使います。サーバー内部は関数レベルでスタブやモックされていません。複数のリクエストを連鎖させるテストも含まれます。例えば DELETE のテストでは、最初にリソースを POST し、次に DELETE し、最後に GET で 404 を確認するといった具合で、リクエストライフサイクルをまたいで副作用が正しく永続化されることを検証します。このマルチリクエストでブラックボックスなアプローチは、統合テストを統合テストたらしめる特徴です。
品質面では、このスイートには明確な強みがあります。各エンドポイントについて正常系と異常系の両方を体系的にカバーし、OpenAPI 仕様に記載された具体的な HTTP ステータスコード(200、400、404、405)を検証します。エフェメラルポートとインメモリのシードデータを使用しているため、スイートは完全に自己完結しており決定的です。ネットワーク依存もポートの衝突もなく、どのマシンでも再現可能です。破壊的な操作はレスポンスコードだけを信用せず、後続の読み取りで検証します。
要するに、これは API の形状とエラーハンドリングに対する CI の高速フィードバックに適した、実用的な契約レベルの統合スイートです。プロダクション品質の信頼性に到達するには、テストごとの状態分離、完全な JSON スキーマ検証、認証のカバレッジ、そして実サービスに対する定期的な実行が加わると良いでしょう。
詳細: 削除ライフサイクル全体のテスト
Kiro が生成したテストの中でも、より興味深いものの 1 つは、単にエンドポイントを呼び出してステータスコードを確認するだけのものではありません。1 つのテストケースで、リソースのライフサイクル全体を検証します。
このテストが興味深いのは、DELETE のレスポンスだけを信用していない点です。多くの素朴なテストスイートは 200 ステータスコードを確認するだけで止まります。「サーバーが成功したと言ったのだから、成功した」というわけです。しかしそれは状態が実際に変化したかどうかを何も証明していません。バグのあるサーバーは 200 を返しつつ、レコードの削除に静かに失敗するかもしれません。
本当に消えている、ということです。
その代わりに、Kiro は 3 段階のテストを生成しました。
-
Arrange:既知の ID を持つ新しい pet を POST し、正常に作成されたことを確認します。
-
Act:その pet を DELETE し、サーバーが操作を受け付けたことを検証します。
-
Verify:同じ ID を GET し、サーバーが
404を返すことを検証します。
このパターンは「ラウンドトリップ検証」と呼ばれることがあり、うわべだけのテストと意味のある統合テストを分けるものです。API の状態が実際に遷移することを証明します。すなわち、存在するリソースは破棄でき、いったん破棄されれば本当に消えているということです。スタックのどこかの層(ルーティング、ハンドラのロジック、データストア)が削除を黙って取りこぼしても、GET による検証がそれを捕まえます。
これはテストが自己完結している好例でもあります。テストは、先行するテストによって書き換えられたかもしれないシードデータに依存するのではなく、自分自身でテストデータを用意します。これにより、テストの合否が実行順序に左右されなくなります。テストごとに状態をリセットしないスイートでは、これは小さくとも重要な品質シグナルです。
実 API に対して実行する
生成されたテストがモックの外でも通用するかを検証するには、1 つの環境変数を設定するだけで、開発者はスイートを実際の Petstore サーバーに向けることができます。
PETSTORE_URL=https://petstore.swagger.io npm test
あるいは Kiro に「Run the tests with the real server」とプロンプトを与えます。これにより、コードを変更することなくまったく同じテストが実行されますが、対象がローカルの Express モックではなく実稼働の共有バックエンドになります。
失敗が発生したとき、それらは通常いくつかの認識可能なカテゴリに分類されます。
-
実 API が仕様より寛容な場合。Swagger 定義では不正な入力に対して
405を文書化していても、実サーバーはそれを静かに受け入れて200を返すことがあります。モックの方が現実より厳しかったというわけです。 -
エラーコードの意味が異なる場合。モックは非数値 ID に対して
400を返すかもしれませんが、実サーバーは404を返すかもしれません。どちらも擁護可能です。同じ仕様の異なる解釈を表しているだけです。 -
レスポンス形状が期待と一致しない場合。テストが文字列として期待するフィールドが JSON オブジェクトとして返ってきたり、ネストされたプロパティが完全に欠落していたりします。
-
共有状態の前提が崩れる場合。シードされたデータ(事前にロードされたユーザーや pet など)に依存するテストは、実サーバーがそれらのテストデータを持たないために失敗します。
このようなことが起きたときの推奨は、失敗をやみくもに「修正」しないことです。代わりに、それぞれを切り分けの問いとして捉えます。モックが間違っているのか、テストが間違っているのか、ドキュメントが間違っているのかということです。そこから次のように進めます。
-
実サーバーがより寛容な場合は、モックを緩めて合わせるか、テストをモック専用としてタグ付けするかを判断します。
-
エラーコードが異なる場合は、単一の信頼できる情報源(通常は実サーバーの実際の振る舞い)に揃え、モックとテストの期待値の両方を更新します。
-
共有状態が問題である場合は、テストを自己完結型にします。検証前に自分自身でテストデータを用意し、ローカルにしか存在しないデータに依存しないようにします。
ポイントは、初日から両モードで全テストを通すことではありません。両方のターゲットに対して実行することで、前提が現実から乖離している箇所が浮かび上がり、そのギャップを埋める道筋が体系的に得られるということです。
認証された内部 API に適応する
Petstore API は認証を求めないパブリックなサンドボックスです。一方、実際の社内 API はほとんどの場合認証を必須とします。認証付きエンドポイントにこのアプローチを適応させる方法を示します。
まず、認証設定に対応できるようにテスト設定を拡張します。資格情報をハードコードするのではなく、外部から渡せるようにすることで、同じスイートを複数の環境で動かせるようにします。
// config.js
module.exports = {
baseURL: process.env.API_BASE_URL || 'http://127.0.0.1:3000',
auth: {
type: process.env.AUTH_TYPE || 'none', // 'none', 'bearer', 'apiKey', 'basic'
token: process.env.AUTH_TOKEN,
apiKey: process.env.API_KEY,
apiKeyHeader: process.env.API_KEY_HEADER || 'X-API-Key',
username: process.env.AUTH_USERNAME,
password: process.env.AUTH_PASSWORD,
},
};
次に、設定された認証タイプに基づいて適切な資格情報を付与する共有クライアントファクトリーを構築します。
// client.js
const axios = require('axios');
const config = require('./config');
function createClient() {
const headers = {};
switch (config.auth.type) {
case 'bearer':
headers['Authorization'] = `Bearer ${config.auth.token}`;
break;
case 'apiKey':
headers[config.auth.apiKeyHeader] = config.auth.apiKey;
break;
case 'basic':
const encoded = Buffer.from(
`${config.auth.username}:${config.auth.password}`
).toString('base64');
headers['Authorization'] = `Basic ${encoded}`;
break;
}
return axios.create({
baseURL: config.baseURL,
headers,
validateStatus: () => true,
});
}
module.exports = { createClient };
これで、すべてのテストファイルが共有クライアントを使用し、資格情報はコードの外に保たれます。
# トークン認証のステージング API に対して実行
AUTH_TYPE=bearer AUTH_TOKEN=eyJhbG... API_BASE_URL=https://api.internal.example.com npm test
# API キーで保護されたサービスに対して実行
AUTH_TYPE=apiKey API_KEY=sk-live-abc123 API_BASE_URL=https://gateway.internal.example.com npm test
これを整えれば、認証の強制そのものを検証する専用テストも追加できます。資格情報なしのリクエストが拒否されること、期限切れトークンが 401 を返すこと、不十分なスコープが 403 を返すことなどです。これらは Petstore のサンドボックスでは試せないものの、内部サービスではしばしば最も重要となるテストです。
Kiro ヘッドレスモードでテスト再生成を自動化する
テストスイートを一度生成できるだけでも有用ですが、本当の価値は、API が進化しても両者を同期させ続けられる点にあります。Kiro CLI のヘッドレスモードを使えば、CI/CD パイプラインから Kiro をプログラムで実行できます。ブラウザもインタラクティブな端末も不要です。API キーを環境変数として設定し、プロンプトを渡せば、Kiro が一連の処理をエンドツーエンドで実行します。
まとめ
本記事では、Kiro を使って Swagger 仕様から完全な Node.js API テストスイートを数秒で生成する方法を示しました。生成されるプロジェクトには、HTTP テストクライアント、Express のモックサーバー、モック API と実 API を切り替える設定トグル、テストレポートが含まれ、外部のテストフレームワーク依存はありません。
このアプローチは、API 仕様をテストコードに手作業で翻訳する手間を取り除き、包括的な API テストカバレッジを達成するための体系的で再現可能な方法を提供します。Swagger または OpenAPI 仕様を持つあらゆる API に同じパターンを適用できます。
Kiro を始めるには、kiro.dev をご覧ください。
翻訳は Solutions Architect の吉村が担当いたしました。




