OTP と 2FA ログインのテストを自動化する方法
二要素ログインは、面倒なせいでチームが自動テストを後回しにしがちなフローの典型です。しかし、リグレッションが起きると最も痛い場所でもあります。ケースは 2 つあり、どちらも自動化できます。関連するフローについては、パスワードリセットメールのテストとマジックリンクログインもご覧ください。本記事は開発者のためのメールテストガイドの一部です。
ケース1:メールまたは SMS の OTP
コードがメールで届く場合、レシピはどのメールテストとも同じです。使い捨て受信トレイを払い出し、ログインを発火させ、API 経由でメッセージを読み、数字を抽出します。受信トレイはテストごとにひとつ作り、OTP が着地するまでポーリング(または webhook で待機)します。
const inbox = await createInbox()
// ...submit the login form with inbox.address...
const msg = await waitForMessage(inbox.id, 30000)
const otp = msg.text.match(/[0-9]{6}/)[0]
// ...type otp into the verification field...
ブラウザ駆動の完全版は Playwright メールテストチュートリアルを、受信トレイ用ヘルパーは使い捨てメール API ガイドをご覧ください。
ケース2:認証アプリ(TOTP)
2FA に認証アプリを使う場合、電話は不要です。コードは共有シークレットから TOTP アルゴリズムで導出されるからです。そのシークレットをテスト用の環境変数として保存し、otplib などのライブラリでテスト内でコードを生成します。
import { authenticator } from 'otplib'
const token = authenticator.generate(process.env.TOTP_SECRET)
// ...type token into the 2FA field...
このシークレットは、アプリがセットアップ用の QR コードにエンコードするものと同じです。登録時にそれを表示し、テスト環境専用に保存しておきましょう。
テスト環境での戦略
どちらの道も使いにくいときは、チームとテスト専用の抜け道について相談しましょう。ステージング環境で常に通る特別なトークン、指定したテストユーザーで 2FA を無効化する、CI の IP からのリクエストではスキップする、などです。実際のログイン経路をきちんと通せる範囲で、できるだけ小さいバイパスを選んでください。
はじめましょう
メールベースのコードならメールボックスを作成し、OpenAPI 経由で読み取ります。TOTP なら共有シークレットをつなぎ込みます。いずれの場合も、テストごとに受信トレイかシークレットをひとつに保てば、2FA のテストスイートは安定します。