まず結論から
-
REST Assuredが適しているのは サービス本体と同じ言語、同じレビュー、同じビルドのプロセスでAPIテストを扱いたいJVMチームです。
-
TestSpriteが適しているのは アサーションの構文ではなく、カバレッジの広さと4つの状態管理の課題がボトルネックになっている場合です。
-
両方を併用すべきなのは 実際に人の手で保守されているREST Assuredのスイートがある場合です。意図して仕様化したテストはそのまま残し、その周囲に生成されたカバレッジの広さを足してください。
項目別の比較
| 観点 | REST Assured | TestSprite |
|---|---|---|
| 概要 | リクエストを送信し、レスポンスを検証するためのJava DSL | APIのカバレッジを生成し、実行し、保守するサービス |
| テストを書くのは誰か | 自社のエンジニアが、JavaまたはKotlinで記述 | 仕様または探索から生成し、自然言語で調整 |
| 読みやすさ | 非常に優れています。given / when / thenが文章のように読めます | テストケースは平易な言葉で記述されます |
| セッションの扱い | 自分で書くフィルター、またはベースとなる仕様 | Auto-Authentication。設定は一度だけ |
| 呼び出し間の値の受け渡し | フィールドに取り出し、自分で引き回す | Dynamic Variables |
| 実行順序とクリーンアップ | JUnitの順序指定と、自分で保守するティアダウン | 自動的に導出される順序とAuto-Cleanup |
| 適しているチーム | テストを書き、保守する余力のあるJVMチーム | 専任のQA機能を持たずにカバレッジの広さを必要とするチーム |
REST Assuredが正解になる場面
コードベースの一部としてのテスト。 同じ言語、同じレビュー、同じビルド。チームによってはこれは譲れない条件であり、それは妥当な立場です。
複雑なカスタムアサーション。 正しさの判定にフィールドの比較ではなく本物のロジックが必要な場合、汎用言語こそが適したツールです。
既存のJVM資産。 すでに手元にある共有フィクスチャ、ドメインオブジェクト、ビルドツール。
自分たちの仕事として残るもの
セッションは期限切れになり、識別子は呼び出し間を引き回す必要があり、他のエンドポイントより先には呼べないエンドポイントがあり、実行のたびにレコードが残ります。REST Assuredはこれらのいずれについても立場を持ちません。DSLとしてはそれが正しい姿ですが、結果として4つすべてが自分たちのテスト基盤の側に落ちてきます。
もう一つ、カバレッジの形にも問題があります。手書きのスイートがカバーするのは、誰かが覚えていた範囲だけです。そして本番環境で問題を起こすエラーパスや境界値こそ、スプリントの終盤には誰も書かないものです。これら4つの仕組みについては、 APIテストのドキュメントで説明しています。
フィクスチャのグラフ問題を具体的に
REST Assuredのスイートが、得られる価値以上のコストを生み始める分岐点は、たいていテストそのものではなくJUnitのフィクスチャに現れます。
あるテストには注文が必要です。注文には顧客と商品が必要です。その顧客には特定のティアのアカウントが必要です。フィクスチャとして表現すればこれは小さなツリーであり、JUnitは何の問題もなく組み立てます。ところが2つ目のテストでは同じ顧客に別の商品が必要になり、3つ目のテストでは顧客が2人必要になります。こうなるとツリーはグラフになり、フィクスチャは引数を取り始め、セットアップのコードはアサーションよりも長くなります。
これはいずれも言語の問題ではなく、DSLの使い勝手を良くしても解決しません。ツリーをモデルとするフレームワークの上で依存関係のグラフを表現することのコストであり、専用に設計されたレイヤーが取り除くのはまさにこの部分です。
両方を併用する
意図して仕様化したケースと、本物のロジックを必要とするアサーションには、REST Assuredを使い続けてください。API全体にわたる広さは、生成されたカバレッジに任せます。どちらも同じパイプラインから実行できます。
評価するなら、わざと壊してみる
保存ボタンを押してもデータが保持されなくなる、といった実際のリグレッションを混入させ、それぞれのツールが何を報告するかを見てください。確認するのは3点です。テストは失敗するか、その失敗は実際の食い違いを名指しできているか、そして修正にあたる人やエージェントは、経緯を一から再構築せずにその出力から着手できるか。アサーションに到達すらしなかった実行を成功と報告するツールは、唯一重要なテストに落第しています。
パイプラインが別のチームのものである場合、 GitHub App が最も抵抗の少ない道です。これはwebhookであり、リポジトリには何の変更も加えず、ビルドが新しいバージョンの公開を通知した時点で動き出します。代わりにチェックをリポジトリ上に表示したい場合は、 GitHub Actions のステップで対応できます。詳しくは、 CLIリポジトリをご覧ください。
TestSpriteがスイート単位で引き受ける部分
どのDSLの外側にも残る4つの問題です。セッションの有効期間にはAuto-Authentication、呼び出し間で受け渡す値にはDynamic Variables、順序をフィクスチャの入れ子として書き込むのではなく自動的に導出するためのDependency Chains、そして各実行が作成したデータに紐づくAuto-Cleanupです。
カバレッジは、皆さんの仕様と、稼働中のサービスに対する探索から生成され、その後平易な言葉で調整されます。つまり、境界値やエラーパスが、誰かが夜11時に書かなくても存在するということです。
その結果JVMチームの手元に残るのは、意図して仕様化したケースと本物のロジックを必要とするアサーションのためのREST Assuredであり、その下に保守すべきフィクスチャのグラフはありません。どちらも同じパイプラインから実行できます。
REST Assuredは今もメンテナンスされていますか?
JVMチームの間では今も広く使われています。ここでの議論はライブラリそのものについてではなく、スイート単位のコストがどこに蓄積するかについてのものです。
既存のテストはそのまま残せますか?
残せますし、実際に人の手で保守されているのであれば残すべきです。移行するのではなく、別のレイヤーでカバレッジを追加してください。
Spring Bootのテストサポートはどうですか?
アプリケーションコンテキスト内の統合テストには非常に優れています。ここで扱っているのはデプロイ済みのサービスを外側からテストする話であり、別の問題です。
生成されたカバレッジは自社のドメインを理解できますか?
出発点になるのは、皆さんの仕様と稼働中のサービスです。ドメイン固有のルールはテストケースを調整することで加えていきます。そこでこそ、皆さんの知識が引き続き意味を持ちます。
カバレッジの重複はどう避ければよいですか?
意図して仕様化した部分は手書きのテストに任せ、生成されたカバレッジは広さに向け、多少の重複は安いコストとして受け入れてください。