Scarnox · Blog

CIを緑に保つ:captchaがあるアプリのテスト

会員登録フォームにPopularCaptchaがあり、E2Eテストスイートは会員登録を行う必要があります。するとCIが赤くなります。そこで手っ取り早く思いつくのは、テストビルドでcaptchaをオフにすることですが、それではテストするフローがユーザーが実際に使うフローと違ってしまいます。

この問題から抜け出す方法はいくつかあります。実際のフローをどの程度再現するかは方法ごとに違うので、テストが答えたい問いに合う方法を選んでください。以下は、安上がりなものから、より現実に近いものへの順に並べた選択肢です。

Scarnoxは現在、PopularCaptchaを解決できます。他のcaptchaの種類は近日対応予定なので、以下の解決の選択肢はPopularCaptchaにのみ当てはまります。

1. ユニットテストとローカルテストにはテスト用のキーを使う

多くのcaptchaプロバイダーは、常に合格するテスト用のキーを公開しています。環境を自分で管理していて、フォームが描画されて送信できることだけを確認したい場合に使ってください。テスト用のキーは実際の検証を行わないため、実際のキーを使ったデプロイ済み環境をテストするときには役に立ちません。

2. 自分のステージング環境用のバイパス

チームによっては、captchaトークンの代わりに、バックエンドが受け入れる秘密のヘッダーを追加しているところもあります。高速で無料ですが、テスト専用のコードパスであり、設定を1つ間違えると本番にも存在してしまう可能性があります。使う場合は、環境チェックの内側に置き、秘密の値は長くランダムなものにし、本番環境では拒否されることをテストで確認してください。

3. 検証の呼び出しをモックする

統合テストでは、サーバー側の検証リクエストをスタブ化します。バックエンドのロジック、たとえば検証に失敗したときに何が起きるかを確認するには良い方法です。ただし、フロントエンドがトークンを正しく送っているかについては何も分からないので、他の方法のどれかと組み合わせてください。

4. ステージングとスモークテストで実際に解決する

実際のキー、本物のウィジェット、本物の検証を使って、フロー全体が本当に動くことを証明する必要があるときは、テストの中で解決APIからトークンを取得します。これが、ウィジェットの統合が壊れているかどうかを検出できる唯一の方法です。

Playwrightのヘルパーは次のようになります。

// Playwrightテスト用ヘルパー
export async function solveCaptcha(page) {
  const sitekey = await page.getAttribute("[data-sitekey]", "data-sitekey");
  const r = await fetch("https://api.scarnox.com/api/tasks/create", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SCARNOX_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      captcha_type: "PopularCaptchaTaskProxyless",
      site_key: sitekey,
      site_url: page.url(),
    }),
  });
  const { errorId, solution, errorCode, errorDescription } = await r.json();
  if (errorId !== 0) throw new Error(`${errorCode}: ${errorDescription}`);

  await page.evaluate((t) => {
    document.querySelectorAll('[name="h-captcha-response"],[name="g-recaptcha-response"]')
      .forEach((el) => { el.value = t; });
  }, solution.token);
}

テストの最初ではなく、テスト内でフォームを送信する直前に呼び出してください。トークンはおよそ2分以内に期限切れになるため、テストの前半で時間のかかる手順があると、その猶予を使い切ってしまいます。

解決の回数を最小限にする

実行のたびに会員登録をするスイートは、1週間で多くの解決を発生させることがあります。回数を少なく保つには次のようにします。

ヘルパー内のリトライのルールは、エラー処理とバックオフのガイドのポリシーを再利用してください。

キーをリポジトリの外に置く

キーはCIのシークレットとして保存し、名前はSCARNOX_KEYなどにしてください。テストのコードやフィクスチャには決して書かないでください。漏えいした場合は、ダッシュボードから再生成してください。古いキーはすぐに使えなくなるので、漏えいしたキーで長く解決を実行されることはありません。

CI用には別のキーを使ってください。あるパイプラインが誤動作しても、そのキーだけをローテーションでき、他には触れずに済みます。

自分のステージングで試す

アカウントを作成して無料のトライアルクレジットで始めてください。カード登録は不要です。まずはヘルパーを1つのスモークテストに組み込み、会員登録がきちんと完了することを確認してから、残りのスイートに追加してください。大量に使ったときの費用は、現在の料金で確認できます。

送信後に検証すべきこと

captchaを解決できたことは、ウィジェットの手順が成功したことを示すだけです。送信後には、ユーザーにとって重要なことを検証してください。次のページが読み込まれること、成功メッセージが表示されること、アカウントや注文がデータベースに存在することです。「フォームにエラーがない」で止まるテストは、バックエンドで会員登録が静かに失敗していても、合格してしまうことがあります。

検証は業務上の結果に近い内容にしてください。URL、画面に表示されるメッセージ、テストが作成した1件のレコードを確認します。実行の最後にそのレコードを削除し、次の実行が既知の状態から始まるようにしてください。

スモークテストをスケジュールで実行する

実際に解決するスモークテストは、すべてのプルリクエストではなく、スケジュールで実行してください。たとえば1日1回、ステージングに対して実行します。スケジュール実行は、サイトが夜間に行った変更、たとえば新しいウィジェットのバージョンや変更されたサイトキーを検出します。コミットごとに解決を消費せずに済みます。スケジュール実行が失敗したらチームに通知し、コミットごとのスイートは速い方法で動かし続けてください。

次のステップ