テストが見落とす前にAPIスキーマのドリフトを検出するにはどうすればよいですか?
ステータスコードといくつかのフィールドのみを検証するテストでは、API にフィールドが追加されたり、検証対象外のフィールドが削除されたり、数値が文字列に変更されたりしても合格し続けます。Nexus Studio は各 API レスポンスの形状(値ではなく、フィールド名と型のみ)を保存し、前回の実行結果と比較して変更があれば API_DRIFTED を報告します。NEXUS_API_DRIFT_STRICT=true を設定すると、同様の変更があった場合にテストスイートを失敗させます。
執筆: Nexus Studio チーム、Verdict System LLC(2026年10月27日)
API スキーマドリフトとは何ですか?
スキーマドリフトとは、実行間でレスポンスの形状が変わることです。フィールドの追加、フィールドの削除、またはフィールドの型の変更がこれに該当します。API が進化すること自体は問題ありません。問題は、テストスイートのどこにも変更が示されていなかったために、本番環境で利用側がその変更に初めて気付くことです。
合格しているコントラクトテストがこれを見逃してしまうのはなぜですか?
作成者が想定した内容しかアサーション(検証)していないためです。たとえば validate(res, { status: 200, hasFields: ['id'] }) のようなルールでは、price がルールに含まれていないため、price が数値から文字列に変更されても合格し続けます。そして、価格を合算するクライアント側で障害が発生することになります。
実行可能な例で実際に確認できますか?
これを server.mjs として保存してください。1つのエンドポイントに応答し、SHAPE 変数によってエンドポイントが返す内容(数値としての価格か、新しい currency フィールドが付いた文字列としての価格か)を切り替えます。
import http from 'node:http';
// SHAPE=v1 answers {id, price: 9.99}; SHAPE=v2 answers {id, price: "9.99", currency: "USD"}.
const v2 = process.env.SHAPE === 'v2';
http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(v2 ? { id: 7, price: '9.99', currency: 'USD' } : { id: 7, price: 9.99 }));
}).listen(4010, '127.0.0.1');
この API テストを、ワークスペースの api-tests/rest フォルダ内に APIT900_drift_demo.api.js として保存してください。多くの実際のテストスイートと同様に、ステータスと1つのフィールドを検証します。
// type: rest
import { runApiSuite } from '../../utils/base-api-fixture.js';
await runApiSuite([{
id: 'APIT900-1',
name: 'GET /product/7 returns 200 with an id',
fn: async ({ request, validate }) => {
const res = await request({ method: 'GET', url: '/product/7' });
validate(res, { status: 200, hasFields: ['id'] });
},
}]);
一方の PowerShell ウィンドウでサーバーを起動し、もう一方のウィンドウでテストを実行してください。初回の実行では比較対象がないため、形状を記録して合格します。
$env:SHAPE = "v1"; node server.mjs
$env:API_BASE_URL = "http://127.0.0.1:4010"; nexus api APIT900 --no-app
サーバーを停止し、$env:SHAPE = "v2" で再起動して同じテストを実行してください。テストは依然として合格しますが、実行はもはや API_SECURE ではなくなります。以下は、重要な行のみに短縮した出力です:
schema drift: +1 field, 1 type change
+ currency
~ price: number → string
API_DRIFTED 7ms
1/1 passed
1 endpoint changed shape since the last run, set NEXUS_API_DRIFT_STRICT=true to fail the suite on it
ドリフトによってビルドを失敗させることはできますか?
はい、リクエストに応じて可能です。デフォルトでは、API の変動は欠陥ではなく情報であるため、API_DRIFTED は合格と見なされ、終了コード 0 で終了します。これは独立した行に出力され、実行のエビデンスに差分とともに記録されるため、完全な合格として解釈されることはありません。NEXUS_API_DRIFT_STRICT=true を設定すると、同じ変更でも終了コード 1 で終了します。これを確認するには、この変数を設定した状態で、v1 に対してテストを1回実行し、v2 に対しても1回実行してください。
ベースラインは常に前回の実行です。ドリフトが発生した実行の後は、その新しい形状がベースラインとなるため、同じレスポンスに対する次回の実行ではドリフトは報告されません。
制限事項には何がありますか?
- テストの初回実行時は形状の記録のみが行われます。比較対象となるドリフト元がまだ存在しないためです。
- 形状とは名前と型であり、意味ではありません。仮に
priceが数値のままでドルからセントに変わったとしても、変動として検知されません。 - 比較は合意されたコントラクトではなく、前回の実行に対して行われます。これにより何かが変更されたことは分かりますが、その変更が許可されたものかどうかは分かりません。
- 各テストケースは、最後のリクエストのボディから取得された1つの形状を保持します。リストはその最初の要素によって記述され、オブジェクトは最大200個のキーまで、ネストは6階層で停止します。
どこで確認できますか?
判定ガイドではテストの判定について説明しており、エビデンスページには実行によってディスク上に残されるファイルが一覧表示されています。30日間トライアルでは、ご自身の API テストで同じエンジンを実行できます。