API機能テストの4つのレベル

1. ステータス

  • 200が返ってきたかどうか。

  • 障害は検出できます。本来レコードがあるべきところで空の結果が返ってきても、何の問題もなく通過します。

2. 構造

  • 期待されるフィールドが、期待される型で存在しているか。

  • スキーマのずれは検出できます。値が正しいかどうかについては何も語りません。

3. 値

  • 合計が本当に総和になっているか、ステータスがこの操作で生じるべきものになっているか。

  • 実際の不具合が捕まり始めるのはこのレベルです。

4つ目は 関係です。注文を作成したあと、顧客を取得するとその注文が見えるか。興味深いバグの多くは、1つの呼び出しの内部ではなく2つの呼び出しの間に潜んでおり、そこを見るのはレベル4だけです。

スイートがレベル2で止まる理由

レベル3とレベル4では「正しい」とは何かを知る必要があり、つまり誰かがそれを決めなければならないからです。ステータスと構造は仕様から機械的に導き出せます。値と関係は、プロダクトについての判断を必要とします。

それは確かに難しい作業ですが、同時にそこにこそ価値のすべてがあります。プロダクトのルールを一度も表現しないスイートは、サービスが稼働していることを手の込んだやり方で確認しているだけです。

省略されがちな異常系のケース

エンドポイントごとに、何が拒否されるべきかを問い、そのうえで実際に拒否されることをアサートしてください。範囲外の値、欠落した必須フィールド、他人に属する識別子などです。ボディにエラーオブジェクトを入れたまま200を返すサービスは珍しくなく、このパターンを知らないスイートはいつまでもグリーンを報告し続けます。

スイートの土台に必要なもの

APIテストスイートが最初の1年を生き延びられるかどうかを決めるのは、次の4つです。期限切れになるセッション、実行時にしか存在しない値、互いに依存する呼び出し、そして誰も片付けないレコード。TestSprite はこれらを Auto-Authentication、Dynamic Variables、Dependency Chains、Auto-Cleanup として扱います。詳しくは APIテストのドキュメント。

ここを正しく整えておくことで、インフラではなくレベル3とレベル4に注意を向けられるようになります。

浅い領域の先までカバレッジを広げる

生成されるテストプランは、仕様またはディスカバリーの実行結果を出発点とし、機能、スキーマ、認可、エラーハンドリング、境界値のカテゴリを含みます。そのため異常系のケースは、スプリント終盤に誰かが思い出すかどうかに左右されることなく、初めから存在します。

ターミナル

npm install -g @testsprite/testsprite-cli
testsprite setup

ローカルに何もインストールしたくない場合は、同じセットアップを TestSprite のダッシュボードでも行えます。CLI のその他の機能については CLI リポジトリ。

どのエンドポイントにレベル4を適用するかを選ぶ

関係のアサーションは最も価値が高く、同時に最もコストもかかるため、あらゆる場所に置くべきではありません。有効な絞り込み方は、誤った答えがどれだけのコストを生むかを問うことです。

お金が動くもの、権限を変更するもの、誰かの意思決定の根拠になるものには、レベル4を適用します。存在しているのに顧客に紐づいていない注文、片側だけ成功した権限付与、内部では整合しているのに元のレコードと食い違うレポート。こうした失敗こそ、コストが高く、しかも静かに起こります。

読み取り専用のレポート用エンドポイント、ヘルスチェック、そして出力を人がその場で目視するようなものには必要ありません。この点を意識的に判断することで、スイートは人が実際に走らせる程度の速さを保てます。

変更ごとに実行する

方法は2つあり、選択の実質的な基準はパイプラインを誰が所有しているかです。ダッシュボードから GitHub App を接続する方法では、リポジトリに一切変更を加える必要がありません。ビルドがすでに発行しているデプロイに反応するからです。一方、 GitHub Actions のステップを追加する方法では、チェックがリポジトリ内に置かれ、ビルドの他の部分と同じようにレビューされます。

TestSprite がレベル2の先へ進ませる仕組み

生成されるテストプランには、機能、スキーマ、認可、エラーハンドリング、境界値の各カテゴリにわたって、異常系のケースが最初から含まれています。手書きのスイートの多くは、まさにこの部分で力尽きます。プランは平易な言葉で調整でき、その調整こそが、あなたのプロダクト知識がスイートに入り込む場所です。

注意を向ける価値があるのは値と関係のレベルであり、そこはプロダクトを理解している人を必要とする領域でもあります。Auto-Authentication は実行を通してセッションを維持し、Dynamic Variables は呼び出し間で値を引き継ぎ、Dependency Chains は各ケースが必要とするものと生み出すものから実行順序を導き、Auto-Cleanup はその実行が作成したものだけを削除します。そのため、費やす時間はインフラではなく「正しいとは何か」に向けられます。

こうして得られるのは、サービスが稼働していることを証明するだけのグリーンなパイプラインではなく、ボディと呼び出し間の関係をアサートし、変更ごとに実行されるスイートです。

ステータスコードのアサーションは無意味ですか?

いいえ、それは最低ラインにすぎません。残したうえで、重要なエンドポイントごとに少なくとも1つ、値レベルのアサーションを追加してください。

「正しい」とは何かをどう決めればよいですか?

コードが何をしているかではなく、プロダクトが何を約束しているかを問いましょう。あるエンドポイントについて誰も答えられないのであれば、その曖昧さ自体が明らかにする価値のあるものです。

すべてのエンドポイントに4つのレベルをすべて適用すべきですか?

いいえ。レベル3とレベル4は、誤った値が実害につながるエンドポイントに絞ってください。レポート用のエンドポイントやヘルスチェックには必要ありません。

生成されたアサーションはどうですか?

機械的に扱えるレベル1とレベル2には有用です。レベル3とレベル4はレビューを通すと効果が上がります。プロダクト知識が入り込むのはそこだからです。

エンドポイントごとに異常系のケースはいくつ必要ですか?

考えられる不正な入力をすべて列挙した10個よりも、意味のある1つか2つのほうが優れています。実際のクライアントが引き起こすような拒否を選んでください。

要点

ステータスと構造は最低ラインであり、それで仕事が終わるわけではありません。

API機能テストにはアサーションの4つのレベルがあり、多くのスイートは2つ目で止まっています。不具合が捕まるのは値と関係のアサーションであり、そして異常系のケースは人が飛ばしてしまう部分です。