APIパフォーマンステストに含まれる3つの問い

キャパシティレイテンシが悪化し始めるまでに、どれだけの同時トラフィックを処理できるか。負荷生成ツールが必要です。リリース前とアーキテクチャ変更後に実行します。
リグレッションこのプルリクエストによって、呼び出しが以前より遅くなっていないか。必要なのはベースラインとの比較であり、高い同時実行数ではありません。
正確性扱いにくい入力を与えた場合も含めて、レスポンスは正しいか。レスポンスボディに対するアサーションが必要です。3つの中で最もコストが低く、最も省略されやすい項目です。

まずリグレッションから自動化すべき理由

キャパシティテストは実行コストが高く、リリースの間で結果が変わることもめったにありません。パフォーマンスのリグレッションはその逆で、プルリクエスト1件ずつ、少しずつ進行します。キャパシティテストがそれを捉えた時点では、半年分の変更が積み上がっており、そのうちのどれが原因なのか見当もつかない状態になっています。

ベースラインと比較する呼び出しごとの単純な計測を、変更のたびに実行しておけば、10倍遅くなったクエリをそれが入った当日に検知できます。四半期に一度のキャパシティレポートよりも、そのほうが価値があります。

土台としての正確性

レスポンスが間違っていれば、計測した時間の数値には何の意味もありません。空の配列を返すエンドポイントは、きわめて高速です。当たり前のことに聞こえますが、フィルタが壊れたまま、レイテンシのグラフだけは優秀なサービスがリリースされるのは、まさにこれが理由です。

したがって、順番は正確性、次にリグレッション、最後にキャパシティとなります。ところが多くのチームはこれを逆の順で進めます。キャパシティテストこそがパフォーマンスの仕事らしく見えるからです。

自動生成されたカバレッジがもたらすもの

APIのテスト計画には境界値やストレスに近い形のケースが含まれており、負荷ではなく構造的な理由でエンドポイントを遅くする入力の組み合わせを明らかにします。ページサイズを大きくすると性能が落ちるクエリは、キャパシティテストが見つけるよりもはるかに早い段階で、ここに現れます。

これは負荷テストではありませんし、その代わりになるものでもありません。その下に位置する、低コストなレイヤーです。

ターミナル

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

何もインストールしたくない場合は、ダッシュボードでも同じことができます。コマンドラインでできるそのほかのすべての操作については、 CLIリポジトリにまとめられています。

セッション、状態、実行順序、クリーンアップについては、 APIテストのドキュメントで解説しています。

リグレッションはたいていどこにあるのか

リリースの間でエンドポイントが遅くなった場合、その原因はほぼ必ず次の3つのいずれかです。これを知っておくと、調査の範囲を大幅に絞り込めます。

インデックスが効かなくなったクエリ、あるいはインデックスでカバーされない条件が加わったクエリ。これが群を抜いて多い原因です。SQL自体は問題なく見えるため、差分からは変化が見えません。

以前は1回のラウンドトリップで済んでいた呼び出しが、複数回になっているケース。多くの場合、ヘルパーがループの中で関連レコードを1件ずつ取得するようになったことが原因です。コードは以前より読みやすくなっているため、そのままレビューを通過してしまいます。

規模が大きくなっただけのケース。プロダクトが成功した結果、かつては5件だったコレクションが500件になり、それがレスポンスに含まれている、といったものです。壊れたものは何もありませんが、エンドポイントはすべてのユーザーにとって遅くなっています。

実行頻度

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

3つのうちTestSpriteがカバーする範囲

3つ目の正確性と、構造的な遅さを浮かび上がらせる境界値ケースです。ページサイズを大きくすると性能が落ちるクエリは、キャパシティテストがそこに到達するよりはるかに早く、しかもごくわずかなコストで、失敗する境界値ケースや遅い境界値ケースとして現れます。

カバレッジはAPI Discoveryと仕様書から得られ、テスト計画は機能、スキーマ、認可、エラー処理、境界値の各カテゴリにわたります。Auto-Authenticationは実行全体を通してセッションを維持し、Dynamic Variablesは呼び出し間で値を引き継ぎ、Dependency Chainsは各ケースが必要とするものと生成するものから実行順序を導き出し、Auto-Cleanupはその実行で作成されたものだけを削除します。

こうして得られるのは、多くのパフォーマンス施策に欠けているレイヤーです。すなわち、すべてのプルリクエストで実行され、エンドポイントが空の結果を返していることに気づく仕組みです。これはスループットのグラフ上では優秀と報告されてしまう類の不具合です。

TestSpriteはレイテンシを計測しますか?

TestSpriteが検証するのはキャパシティではなく正確性です。継続的な同時実行下での応答時間やスループットの計測には、専用のパフォーマンステストツールが必要です。

妥当なベースラインとは何でしょうか?

同じ環境で計測した、自分たちの過去の数値です。他の製品から借りてきた絶対的な目標値は、ほとんど参考になりません。

パフォーマンステストはマージをブロックすべきでしょうか?

重要な経路での大きなリグレッションであれば、ブロックすべきです。小さなばらつきであれば、ブロックすべきではありません。そうしないと、リリースではなくしきい値の調整に時間を費やすことになります。

なぜ数値のばらつきがこれほど大きいのでしょうか?

たいていは共有環境、コールドキャッシュ、データ量の違いが原因です。比較結果を信頼する前に、これらの条件を揃えてください。

1つのツールで3つすべてに対応できますか?

対応できるとうたうツールもあります。しかし実際には、キャパシティの問いには負荷生成ツールが必要で、正確性の問いにはレスポンスボディに対するアサーションが必要です。この両方を1回の実行で高い水準でこなせるツールは、マーケティングの説明ほど多くはありません。

要点

正確性、次にリグレッション、最後にキャパシティの順です。

APIパフォーマンステストは、3つの問いと3つの答えからなります。変更のたびに自動化する価値があるのはリグレッション、そのすべての土台となるのが正確性、そして多くのチームが最初に手をつけるコストの高いものがキャパシティです。