チームは仕様に完全に合致するソフトウェアを構築しても、間違った製品を出荷することがあります。また、欠陥だらけのコードの上に、まさに適切な製品を構築することもできます。この二つの失敗には名前があります。前者は検証(verification)の問題であり、後者は妥当性確認(validation)の問題です。この二つを混同することが、品質プロセスが忙しいだけで効果がない原因となります。
このガイドでは、両方の用語を明確にし、その違いを説明し、Apidogを使ったAPIテストワークフローのどこにそれぞれが当てはまるかを示します。
検証(Verification)とは何か?
検証は「私たちは製品を正しく構築しているか?」と問いかけます。
これは、ソフトウェアがその仕様、設計、および標準に準拠していることを確認します。検証は、作業を文書化された意図と比較します。その意図が正しかったかどうかは問いません。単に実装がそれに合致しているかどうかを問うだけです。
検証は、開発の終わりではなく、開発全体を通して継続的に行われます。一般的な検証活動には以下が含まれます。
- コードレビューとウォークスルー
- 静的解析とリンティング
- 設計およびアーキテクチャレビュー
- スキーマおよびコントラクトチェック
- 関数がそのシグネチャの約束どおりに機能することを確認する単体テスト
重要な特徴は、検証がほとんど内部的なものであることです。それは成果物を別の成果物と比較します。コードを設計と、レスポンスをスキーマと、実装を仕様と、といった具合です。実際のユーザーは必要ありません。もし仕様がエンドポイントがLocationヘッダー付きで201を返すと言っているなら、検証はそれがまさにそうすることを確認します。
妥当性確認(Validation)とは何か?
妥当性確認は「私たちは適切な製品を構築しているか?」と問いかけます。
これは、仕様に何が書かれているかに関わらず、ソフトウェアが実際にユーザーのニーズを満たし、真の問題を解決していることを確認します。妥当性確認は、作業を文書ではなく、現実と使用意図と比較します。
妥当性確認は、ユーザーやステークホルダーが操作できるものができてから、後の方で行われる傾向があります。一般的な妥当性確認活動には以下が含まれます。
- ユーザー受け入れテスト
- ベータプログラムとユーザビリティテスト
- 完全なワークフローのエンドツーエンドテスト
- ステークホルダーデモと承認
重要な特徴は、妥当性確認が外部志向であることです。完成した製品がその文脈で有用であり、正しいかを問いかけます。APIはすべての検証チェックをパスし、OpenAPI仕様に完全に準拠しているにもかかわらず、仕様自体が間違った問題を解決していたために妥当性確認で失敗することがあります。例えば、ページネーションモデルが使い物にならない、または認証フローがクライアントの実際の統合方法に合わない、といったケースです。
妥当性確認と検証:その違い
| 側面 | 検証 (Verification) | 妥当性確認 (Validation) |
|---|---|---|
| 核となる問い | 正しく構築しているか? | 適切なものを構築しているか? |
| 比較対象 | 仕様、設計、標準 | ユーザーのニーズ、現実の使用状況 |
| タイミング | 開発全体を通じて継続的に | 使用可能なものができた後で |
| 一般的な手法 | レビュー、静的解析、単体テスト、スキーマチェック | 受け入れテスト、ベータ、エンドツーエンド、デモ |
| 方向性 | 内部:成果物と成果物 | 外部:製品と現実 |
| 発見するもの | 欠陥、仕様逸脱、コントラクトのずれ | 間違った要件、不適合、ユーザビリティのギャップ |
| 省略した場合のコスト | 良い仕様に合致したバグのあるコード | 間違った問題を解決する洗練された製品 |
この二つは互換性がなく、どちらも他方を置き換えるものではありません。検証が強力で妥当性確認が弱いと、誰も欲しがらない欠陥のない製品ができます。妥当性確認が強力で検証が弱いと、不安定なコードの上に適切なアイデアが実装されることになります。適切なタイミングで両方が必要です。
簡単な覚え方として:検証はドキュメントに対するテストであり、妥当性確認は目的に対するテストです。
APIテストにおける適用方法
APIは、そのOpenAPIまたはスキーマ定義という、明示的で機械可読な仕様を持っているため、この区別を具体的にします。その仕様が検証のベースラインとなります。
APIの検証は、実装をそのコントラクトに対してチェックすることを意味します。
- 各エンドポイントは文書化されたステータスコードを返しますか?これらを一貫させること自体が一つの専門分野です。詳しくはREST APIが使用すべきHTTPステータスコードをご覧ください。
- すべてのレスポンスは、適切なフィールド名と型で文書化されたスキーマに一致しますか?
- 必須パラメーターは指定どおりに正確に適用されていますか?
- エラーフォーマットは文書化されたエラーの形に一致しますか?
ここにはAPIコントラクトテストも含まれます。コントラクトテストは純粋な検証です。それはプロデューサーがコンシューマーが依存する契約を依然として尊重していることを確認します。APIアサーションはステータス、スキーマ、ヘッダーに対する検証作業の単位です。
APIの妥当性確認は、APIが実際にそのコンシューマーに役立つかどうかをチェックすることを意味します。
- クライアントは、不格好な回避策なしに、ログイン、作成、更新、削除といった実際の端から端までのワークフローを完了できますか?
- APIが返すデータは、クライアント開発者が尋ねる質問に実際に答えていますか?
- 認証モデルは、既存の統合にとって実用的ですか?
- 文書化された例は、APIが実際にどのように使用されているかを反映していますか?
複数のリクエストを連鎖させて完全なユーザーの旅を形成するAPIテストシナリオは妥当性確認に近く、単一のエンドポイントのスキーマチェックは検証です。どちらもテストスイートに属します。テストシナリオとテストケースの違いを理解することは、どの層で作業しているかを確認するのに役立ちます。
Apidogがどのように適合するか
ApidogはAPIデザイン、テスト、ドキュメンテーションを一つのワークスペースに保持するため、この区別の両側面をサポートします。
検証においては、APIデザインが仕様そのものです。テストを構築する際、APIを定義するのと同じスキーマに対してレスポンスをアサートするため、検証ではコントラクトの複製が仕様から逸脱することはありません。スキーマアサーション、ステータスアサーション、コントラクトチェックはすべて、信頼できる情報源に対して実行されます。CIを通じてすべてのコミットでそれらを実行します。CI/CDでのAPIテストの自動化は検証を継続的に行い、まさにそれが検証が行われるべき時です。
妥当性確認においては、Apidogのテストシナリオは複数のエンドポイントを完全なワークフローに連結します。ユーザー登録、ログイン、リソース作成、結果確認を行うシナリオを構築し、実際のクライアントが実行するようにそれを実行できます。このエンドツーエンドの演習は、各エンドポイントが仕様の行に一致するだけでなく、APIが実際の問題を解決していることを確認する方法です。
レポートはループを閉じます。Apidogはステップごとの結果を生成するため、検証の失敗(スキーマの不一致)と妥当性確認の失敗(壊れた複数ステップのワークフロー)の両方が可視化され、区別され、追跡可能になります。
自身のAPIに対するコントラクトレベルの検証とワークフローレベルの妥当性確認の両方を設定するには、Apidogをダウンロードしてください。
実世界の例
決済APIを構築するチームを想像してください。仕様書には、POST /paymentsが金額と通貨を受け入れ、payment_idを含む201を返し、不正な通貨は400で拒否すると書かれています。
このAPIの検証はスムーズに進みます。コードレビューでハンドラーが設計に合致していることを確認します。スキーマアサーションで、すべてのレスポンスが文書化されたフィールドとタイプを持っていることを確認します。コントラクトテストで、400エラーの形式が仕様通りであることを確認します。ステータスコードのチェックもすべて合格です。あらゆる検証の尺度から見て、APIは正しく構築されています。
その後、最初の実際のクライアントが統合します。彼らは、APIが金額を浮動小数点数として受け入れるため、0.1 + 0.2が顧客の請求書と一致しない値に丸められることを発見します。仕様には「amount: number」と書かれていました。実装はそれを完璧に尊重しました。仕様が間違っていたのです。金額は決して浮動小数点数であってはなりません。検証ではこれを決して発見できませんでした。なぜなら、検証は実装を仕様と比較するだけであり、両者とも一致していたからです。
妥当性確認がこれを捉えます。クライアントが実際の支払いをエンドツーエンドで実行し、請求書と照合した瞬間に、丸め誤差が表面化します。修正はコードの欠陥報告ではありません。仕様変更であり、金額は整数型の最小単位になります。これが妥当性確認の発見の特徴です。その答えは「コードを仕様に合わせて修正する」ではなく、「仕様自体が間違っていた」なのです。
これが両方が重要である理由です。検証は、壊れたコントラクトの完璧な実装を出荷したでしょう。実際の消費者がAPIを使用するようにAPIを行使する妥当性確認こそが、そのコントラクトが問題であることを明らかにする唯一の方法なのです。
実践的なチェックリスト
APIリリースの際には、両方の項目を実行してください。
検証(仕様に対する確認):
- すべてのエンドポイントが文書化されたステータスコードを返す
- すべてのレスポンスがそのスキーマに準拠している
- 必須パラメーターが適用されている
- エラーレスポンスが文書化された形式に一致している
- すべてのコンシューマー向けエンドポイントでコントラクトテストが合格する
妥当性確認(目的に対する確認):
- 新規クライアントがコアワークフローをエンドツーエンドで完了できる
- 返されるデータが実際のクライアントの質問に答えている
- 認証フローが実際の統合パターンで機能する
- 文書化された例が実際の使用状況と一致している
- ステークホルダーがAPIが意図された問題を解決していることを確認する
最初の項目のみが合格した場合、おそらく間違った設計の正しい実装ができていることになります。2番目の項目のみが合格した場合、不安定なコードで適切なアイデアが実現されていることになります。自信を持ってリリースするには、両方が必要です。
よくある質問
検証と妥当性確認はどちらを先に行いますか? 検証はコードが存在し次第、仕様に対してコードをチェックできるため、最初に始まり継続的に実行されます。妥当性確認は、実際のニーズに対して実行できる使用可能な製品ができてから行われます。
テストは妥当性確認と同じですか? いいえ。テストは両方を網羅します。単体テストやスキーマチェックは検証であり、受け入れテストやエンドツーエンドテストは妥当性確認です。「テスト」という用語は、その全範囲をカバーします。
ソフトウェアは検証をパスしても妥当性確認で失敗することがありますか? はい、よくあります。実装は仕様に完璧に合致しているが、仕様自体が間違った問題を解決している場合です。その製品は検証済みですが、妥当性確認はされていません。
これはAPIコントラクトテストにどのように適用されますか? コントラクトテストは検証です。APIがコンシューマーとの文書化された契約を依然として尊重していることを確認します。その契約が正しかったかどうかを確認するものではありません。それは妥当性確認の仕事です。
どちらがより多くのバグを発見しますか? 検証は継続的に実行され、小さな逸脱を早期に捕捉するため、数としてはより多くの欠陥を発見します。妥当性確認は発見する問題の数は少ないですが、よりコストのかかる問題を発見します。なぜなら、妥当性確認の失敗は通常、コードだけでなく要件や設計が間違っていたことを意味するからです。
自動化は両方をカバーできますか? 自動化は検証をうまく処理します。スキーマチェック、コントラクトテスト、ステータスアサーションはすべてのコミットで実行されます。妥当性確認は、現実世界との適合性に関する判断に依存するため、完全に自動化するのはより困難ですが、エンドツーエンドのワークフローテストはその意味のある部分を自動化します。
