kubell Creator's Note

ビジネスチャット「Chatwork」のエンジニアのブログです。

ビジネスチャット「Chatwork」のエンジニアのブログです。

読者になる

Claude Codeに「QA専門エージェント」を組ませたらテスト内容が劇的に変わったお話

こんにちは。認証グループのいまひろです。

以前公開した「Claude CodeでJiraのチケット駆動開発を強固に加速させる!」という記事で、Claude Codeを開発チームの一員として迎え入れ、Jiraを中心とした開発プロセスを加速させた事例をご紹介しました。

私たち認証グループでは、Jiraを軸にした開発プロセスを採用しています。その中でGherkinのテストケース作成実装のフェーズをClaude Codeに任せることで、効率的に開発生産性とプロダクト品質を向上させることを目指しています。

適切に運用されたClaude Codeは、まるでスーパーマン(?)のように、ストーリーチケットに対して圧倒的なスピードでテストケースの作成や実装を行ってくれます(もちろん、人間のレビューを挟みます)。

しかし、この開発スピードの向上という大きなメリットの裏で、私たちはある課題に直面しました。それは、「テストの設計者と実装者が同じAI人格である」という問題です。

「テストを設計する者と、実装する者は、分けるべきである」という原則に立てば、この構成は少し危うさを孕んでいるのかもしれません。実装者自身が実装前にテストを設計する利便性は、時として品質を損なうリスクを内包します。そしてこれは、相手がAIであっても例外ではないように感じました。

今回の記事では、この課題をどう乗り越えようとしているのか、そしてClaude Codeのサブエージェント機能によりAIによる「チーム開発」を実践した結果、何が起きたかをご紹介します。

課題:単一AIモデルにおける「視点の偏り」

実装AI自身が、実装前にテストシナリオも設計する。このアプローチは一見、仕様理解の齟齬がなく最も効率的に見えます。しかし、実際には以下のような課題が潜んでいました。

  • 確認バイアスの発生 AIは自らがこれから実装するロジックを前提にテストシナリオを設計するため、どうしても正常系のシナリオに偏りがちです。これでは、仕様の解釈ミスや、実装者が考慮していなかったケースを発見することは困難です。

  • テスト観点の不足 実装者の視点だけでは、ユーザーの予期せぬ操作、セキュリティ上の脅威、パフォーマンスの問題といった、QAの専門家であれば持っているはずの多角的な視点が、テスト設計の段階で抜け落ちてしまいます。

このままでは、テストが「これから書く実装を通すための設計図」になってしまい、品質を保証するという本来の目的を果たせなくなる危険性がありました。

解決策:「実装AI」と「QAエージェント」の分離によるテストファースト開発

この課題に対し、Claude Codeに最近導入されたサブエージェント機能が有効な解決策になると考えました。

この機能を使うと、Claude Code上に特定の役割やペルソナに特化した別人格のAIを作成することができます。

そこで今回は、この機能を利用して「経験豊富なQAエンジニア」として振る舞うAIエージェントを新たにチームへ迎え入れ、これまで単一のAI人格が担っていたプロセスを、以下のように別のエージェントへ割り振り、役割を明確に分離するアプローチを試すことにしました。

  • テストシナリオ作成フェーズ

    • サブエージェントとしてジョインしたQA担当のAI(QAエージェント)が機能要件を元に、網羅的で多角的な観点からGherkinテストシナリオを作成します。これが、これから開発する機能が「満たすべき仕様ゴール」となります。
  • 実装フェーズ

    • 実装担当のAIが、このテストシナリオをすべてパスすることを目標として、具体的なコードを実装します。

これにより、「一人のAIによる単独作業」から、「QAが定義したゴールに向かって実装者が開発を進める」という、AIによるテストファースト開発と役割分担を実現しました。

Gherkinテスト比較:役割分担はテスト設計をどう変えたか?

この分業体制が、テストシナリオの質にどれほどのインパクトを与えたか。多要素認証(MFA)機能に関するユースケースを例に、生成されたGherkinテストを比較してみましょう。

別AIで作成したサンプルユースケース(クリックで詳細表示)

### **チケット概要**

  * **課題ID:** SAGA-9999
  * **チケットタイプ:** ストーリー
  * **サマリー:** ユーザーが多要素認証(MFA)を有効化し、より安全にアカウントへログインできるようにする

### **Description**

#### **As a (ユーザーの役割)**

セキュリティ意識の高いユーザーとして

#### **I want to (実現したいこと)**

多要素認証(MFA)を有効化し、ログイン時にパスワードに加えてスマートフォンアプリで生成されるワンタイムパスワードを入力したい

#### **So that (なぜそれをしたいか)**

万が一パスワードが漏洩した場合でも、第三者による不正ログインを防ぎ、アカウントを安全に保ちたい

-----

### **Acceptance Criteria(受け入れ条件)**

開発された機能が、このストーリーの要件を満たしているかを検証するための条件です。以下に具体的な例を挙げます。

  * ユーザーは、アカウント設定画面から多要素認証(MFA)の有効化設定ができること。
  * MFAを有効化する際、スマートフォンアプリ(例:Google Authenticator)でQRコードを読み取って登録できること。
  * MFAを有効化後、次回ログイン時にパスワード入力に加え、ワンタイムパスワードの入力が求められること。
  * ワンタイムパスワードが正しく入力された場合のみ、ログインが成功すること。
  * ユーザーは、いつでもMFAを無効化できること。
  * MFA設定の変更(有効化・無効化)を行った際、確認用の通知メールが送信されること。

-----

### **その他考慮事項**

  * **技術的な詳細(任意):**
      * MFAの実装には、`otpauth-uri` 標準を利用する。
      * バックエンドでは、MFAライブラリ(例:`pyotp` for Python)を導入する。
  * **タスク分割のヒント:**
      * **バックエンドタスク:** MFAの登録・検証APIエンドポイントの実装
      * **フロントエンドタスク:** MFA設定画面のUI開発、QRコードの表示機能実装
      * **テストタスク:** E2Eテストの作成、セキュリティテストの実施

従来の方法(単一AI)で作成されたGherkinテスト

まず、実装AI自身がテストシナリオも設計した場合です。

実装AIが設計したテストシナリオ(クリックで詳細表示)

Feature: 多要素認証(MFA)管理
  As a セキュリティ意識の高いユーザー
  I want to 多要素認証を有効化・管理する
  So that 不正アクセスからアカウントを保護できる

  Background:
    Given 登録済みユーザーである
    And アカウントにログインしている

  Scenario: 初回MFA有効化の成功
    Given アカウント設定画面を開いている
    And MFAが現在無効になっている
    When "MFAを有効にする"ボタンをクリックする
    Then QRコードが表示される
    And 認証アプリでスキャンする手順が表示される
    When 認証アプリでQRコードをスキャンする
    And 生成された6桁の確認コードを入力する
    And "確認して有効化"ボタンをクリックする
    Then "MFAが正常に有効化されました"という成功メッセージが表示される
    And MFA有効化の確認メールを受信する
    And アカウント設定でMFAが"有効"と表示される

  Scenario: MFA無効化の成功
    Given アカウント設定画面を開いている
    And MFAが現在有効になっている
    When "MFAを無効にする"ボタンをクリックする
    Then "MFAを無効にしてもよろしいですか?"という確認ダイアログが表示される
    When 確認のため現在のパスワードを入力する
    And "無効化を確認"ボタンをクリックする
    Then "MFAが正常に無効化されました"という成功メッセージが表示される
    And MFA無効化の確認メールを受信する
    And アカウント設定でMFAが"無効"と表示される

  Scenario: MFA有効時のログイン成功
    Given アカウントでMFAが有効になっている
    And ログインページを開いている
    When メールアドレス"user@example.com"を入力する
    And 正しいパスワードを入力する
    And "サインイン"ボタンをクリックする
    Then MFA確認ページにリダイレクトされる
    And "6桁の確認コードを入力してください"というプロンプトが表示される
    When 認証アプリから現在の確認コードを入力する
    And "確認"ボタンをクリックする
    Then アカウントに正常にログインする
    And ダッシュボードにリダイレクトされる

  Scenario: ログイン時の誤ったMFAコード入力
    Given アカウントでMFAが有効になっている
    And ログインページを開いている
    When メールアドレス"user@example.com"を入力する
    And 正しいパスワードを入力する
    And "サインイン"ボタンをクリックする
    Then MFA確認ページにリダイレクトされる
    When 誤った確認コード"123456"を入力する
    And "確認"ボタンをクリックする
    Then "無効な確認コードです。もう一度お試しください。"というエラーメッセージが表示される
    And MFA確認ページに留まる
    And 残り試行回数が2回と表示される

  Scenario: MFA設定時の誤った確認コード入力
    Given アカウント設定画面を開いている
    And MFAが現在無効になっている
    When "MFAを有効にする"ボタンをクリックする
    And QRコードが表示される
    And 誤った確認コード"000000"を入力する
    And "確認して有効化"ボタンをクリックする
    Then "無効な確認コードです。認証アプリを確認して再度お試しください。"というエラーメッセージが表示される
    And MFAは無効のままである
    And QRコードは引き続き表示される

  Scenario: MFAコード入力の最大試行回数超過
    Given アカウントでMFAが有効になっている
    And 正しい認証情報入力後のMFA確認ページにいる
    When 誤った確認コードを3回入力する
    Then "最大試行回数を超えました。再度ログインしてください。"というエラーメッセージが表示される
    And ログインページにリダイレクトされる
    And ログイン試行失敗のセキュリティアラートメールを受信する

  Scenario: 認証アプリが使用できない場合のリカバリーコード使用
    Given アカウントでMFAが有効になっている
    And リカバリーコードを保存している
    And 正しい認証情報入力後のMFA確認ページにいる
    When "リカバリーコードを使用"をクリックする
    And 有効なリカバリーコードを入力する
    And "確認"ボタンをクリックする
    Then アカウントに正常にログインする
    And 使用したリカバリーコードが消費済みとしてマークされる
    And 新しいリカバリーコードを生成するようリマインダーが表示される

  Scenario: 確認を完了せずにMFA有効化を中断
    Given アカウント設定画面を開いている
    And MFAが現在無効になっている
    When "MFAを有効にする"ボタンをクリックする
    And QRコードが表示される
    And 確認を完了せずにページから離れる
    When アカウント設定画面に戻る
    Then MFAは"無効"と表示されたままである
    And MFA設定プロセスを最初からやり直す必要がある

  Scenario: MFA無効化時の誤ったパスワード入力
    Given アカウント設定画面を開いている
    And MFAが現在有効になっている
    When "MFAを無効にする"ボタンをクリックする
    And 確認ダイアログが表示される
    And 誤ったパスワードを入力する
    And "無効化を確認"ボタンをクリックする
    Then "パスワードが正しくありません。もう一度お試しください。"というエラーメッセージが表示される
    And MFAは有効のままである
    And 確認ダイアログは開いたままである

このテストは、機能の基本的な流れ(有効化・無効化・ログイン)と、いくつかの代表的なエラーケースをカバーしており、決して悪いものではありません。

しかし、開発者視点が強く、あくまで「実装した機能が仕様通り動くか」の確認に留まっている印象です。試行回数の表示やリカバリーコードの使用といった点は考慮されているものの、より深いQA観点は不足しているように見えます。

QAエージェントが作成したGherkinテスト

次に、専門のQAエージェントが設計したテストシナリオです。

専門のQAエージェントが設計したテストシナリオ(クリックで詳細表示)

Feature: 多要素認証(MFA)機能
  As a セキュリティ意識の高いユーザーとして
  I want to 多要素認証(MFA)を有効化し、ログイン時にパスワードに加えてワンタイムパスワードを入力したい
  So that 万が一パスワードが漏洩した場合でも、第三者による不正ログインを防ぎ、アカウントを安全に保ちたい

  Background:
    Given ユーザー "test.user@example.com" が登録済みである
    And パスワード "SecurePass123!" でログインできる状態である
    And スマートフォンにGoogle Authenticatorアプリがインストール済みである

  @smoke @critical
  Scenario: MFAの有効化から無効化までの完全なフロー
    Given ユーザーがログイン済みである
    When アカウント設定画面を開く
    And セキュリティ設定タブを選択する
    And "多要素認証(MFA)を有効化" ボタンをクリックする
    Then QRコード画面が表示される
    And "Google Authenticatorでスキャンしてください" のガイダンスが表示される
    
    When スマートフォンでQRコードをスキャンする
    And 生成された6桁のワンタイムパスワード "123456" を入力する
    And "有効化" ボタンをクリックする
    Then "MFAが正常に有効化されました" の成功メッセージが表示される
    And MFA設定有効化の確認メールが "test.user@example.com" に送信される
    And MFAステータスが "有効" と表示される

    When 一度ログアウトする
    And メールアドレス "test.user@example.com" とパスワード "SecurePass123!" でログインを試行する
    Then "ワンタイムパスワードを入力してください" の画面が表示される
    
    When Google Authenticatorで生成された6桁のOTP "789012" を入力する
    And "ログイン" ボタンをクリックする
    Then ログインが成功し、ダッシュボード画面が表示される

    When アカウント設定画面を開く
    And セキュリティ設定タブを選択する
    And "MFAを無効化" ボタンをクリックする
    And 現在のパスワード "SecurePass123!" を入力する
    And 確認ダイアログで "無効化する" を選択する
    Then "MFAが正常に無効化されました" の成功メッセージが表示される
    And MFA設定無効化の確認メールが "test.user@example.com" に送信される
    And MFAステータスが "無効" と表示される

  @regression
  Scenario: 無効なOTPでのログイン失敗
    Given MFAが有効化済みのユーザーがいる
    When メールアドレス "test.user@example.com" とパスワード "SecurePass123!" でログインを試行する
    And 無効なOTP "000000" を入力する
    And "ログイン" ボタンをクリックする
    Then "ワンタイムパスワードが正しくありません" のエラーメッセージが表示される
    And ログイン画面に留まる
    And ログイン失敗のログが記録される

  @regression
  Scenario: 期限切れOTPでのログイン失敗
    Given MFAが有効化済みのユーザーがいる
    When メールアドレス "test.user@example.com" とパスワード "SecurePass123!" でログインを試行する
    And 30秒以上前に生成された期限切れOTP "456789" を入力する
    And "ログイン" ボタンをクリックする
    Then "ワンタイムパスワードの有効期限が切れています" のエラーメッセージが表示される
    And ログイン画面に留まる

  @regression
  Scenario: 使用済みOTPでのログイン失敗
    Given MFAが有効化済みのユーザーがいる
    And 過去に使用済みのOTP "654321" がある
    When メールアドレス "test.user@example.com" とパスワード "SecurePass123!" でログインを試行する
    And 使用済みのOTP "654321" を再度入力する
    And "ログイン" ボタンをクリックする
    Then "このワンタイムパスワードは既に使用されています" のエラーメッセージが表示される
    And ログイン画面に留まる

  @security @critical
  Scenario: OTP入力の試行回数制限
    Given MFAが有効化済みのユーザーがいる
    When メールアドレス "test.user@example.com" とパスワード "SecurePass123!" でログインを試行する
    And 無効なOTP "111111" を入力して "ログイン" ボタンをクリックする
    And 無効なOTP "222222" を入力して "ログイン" ボタンをクリックする
    And 無効なOTP "333333" を入力して "ログイン" ボタンをクリックする
    And 無効なOTP "444444" を入力して "ログイン" ボタンをクリックする
    And 無効なOTP "555555" を入力して "ログイン" ボタンをクリックする
    Then "試行回数が上限に達しました。しばらく時間をおいてから再度お試しください" のメッセージが表示される
    And アカウントが15分間ロックされる
    And セキュリティアラートメールが送信される

  @edge-case
  Scenario: QRコードの再生成
    Given ユーザーがログイン済みである
    When アカウント設定画面を開く
    And セキュリティ設定タブを選択する
    And "多要素認証(MFA)を有効化" ボタンをクリックする
    Then QRコード画面が表示される
    
    When "QRコードを再生成" ボタンをクリックする
    Then 新しいQRコードが表示される
    And 以前のQRコードとは異なるコードが生成される
    And "新しいQRコードが生成されました" の通知が表示される

  @edge-case
  Scenario: 複数デバイスでのMFA設定
    Given ユーザーがログイン済みである
    And 既に1台のデバイスでMFAが有効化済みである
    When 別のデバイスでGoogle Authenticatorに同じアカウントを追加しようとする
    Then 両方のデバイスで同じOTPが生成される
    And どちらのデバイスのOTPでもログインできる

  @edge-case
  Scenario: MFA有効化中のネットワークエラー
    Given ユーザーがログイン済みである
    When アカウント設定画面を開く
    And セキュリティ設定タブを選択する
    And "多要素認証(MFA)を有効化" ボタンをクリックする
    And QRコードをスキャンして6桁のOTP "123456" を入力する
    And ネットワーク接続が切断された状態で "有効化" ボタンをクリックする
    Then "ネットワークエラーが発生しました。再度お試しください" のエラーメッセージが表示される
    And MFAの有効化が完了していない状態を保つ

  @usability
  Scenario: MFA設定時のガイダンス表示
    Given ユーザーがログイン済みである
    When アカウント設定画面を開く
    And セキュリティ設定タブを選択する
    Then "多要素認証を有効化すると、ログイン時の安全性が向上します" のガイダンスが表示される
    
    When "多要素認証(MFA)を有効化" ボタンをクリックする
    Then QRコード画面が表示される
    And "手順1: スマートフォンにGoogle Authenticatorアプリをインストール" が表示される
    And "手順2: アプリでQRコードをスキャン" が表示される
    And "手順3: 表示された6桁の数字を入力" が表示される
    And Google Authenticatorアプリのダウンロードリンクが表示される

  @usability
  Scenario: OTP入力フィールドの操作性
    Given MFAが有効化済みのユーザーがいる
    When メールアドレス "test.user@example.com" とパスワード "SecurePass123!" でログインを試行する
    Then OTP入力フィールドが表示される
    And 入力フィールドにフォーカスが自動的に設定される
    And プレースホルダーに "6桁のコードを入力" が表示される
    And 数字以外の文字は入力できない
    And 6文字入力すると自動的にフォーカスが次のボタンに移動する

  @security
  Scenario: MFA無効化時の確認フロー
    Given MFAが有効化済みのユーザーがいる
    And ユーザーがログイン済みである
    When アカウント設定画面を開く
    And セキュリティ設定タブを選択する
    And "MFAを無効化" ボタンをクリックする
    Then "本当にMFAを無効化しますか?セキュリティが低下します" の警告ダイアログが表示される
    And "パスワードを再入力してください" の入力フィールドが表示される
    
    When 間違ったパスワード "WrongPassword" を入力する
    And "無効化する" ボタンをクリックする
    Then "パスワードが正しくありません" のエラーメッセージが表示される
    And MFAが有効のまま変更されない

  @security @critical
  Scenario: セッション管理とMFAの関係
    Given MFAが有効化済みのユーザーがいる
    When メールアドレス "test.user@example.com" とパスワード "SecurePass123!" でログインを試行する
    And 有効なOTP "123456" を入力してログインに成功する
    And 8時間後にページを更新する
    Then セッションが期限切れとなりログイン画面にリダイレクトされる
    And 再度メールアドレスとパスワードでログインを試行する
    Then OTP入力画面が再度表示される

  @regression
  Scenario Outline: 異なるOTP形式での入力検証
    Given MFAが有効化済みのユーザーがいる
    When メールアドレス "test.user@example.com" とパスワード "SecurePass123!" でログインを試行する
    And OTP入力フィールドに "<input>" を入力する
    And "ログイン" ボタンをクリックする
    Then "<expected_message>" が表示される

    Examples:
      | input      | expected_message                          |
      | 12345      | 6桁の数字を入力してください                   |
      | 1234567    | 6桁の数字を入力してください                   |
      | abc123     | 数字のみ入力可能です                         |
      | 12 34 56   | スペースは使用できません                      |
      |            | ワンタイムパスワードを入力してください          |

  @notification
  Scenario: MFA設定変更時の通知メール内容
    Given ユーザーがログイン済みである
    When MFAを有効化する
    Then 確認メールが "test.user@example.com" に送信される
    And メールの件名が "【Chatwork】多要素認証が有効化されました" である
    And メールに有効化日時が記載されている
    And メールに使用したブラウザとIPアドレスが記載されている
    And メールに"心当たりがない場合はすぐにパスワードを変更してください"の注意書きがある

  @accessibility
  Scenario: MFA設定画面のアクセシビリティ
    Given ユーザーがログイン済みである
    When アカウント設定画面を開く
    And セキュリティ設定タブを選択する
    Then "多要素認証(MFA)を有効化" ボタンにaria-labelが設定されている
    And QRコード画像にalt属性が設定されている
    And エラーメッセージがスクリーンリーダーで読み上げ可能である
    And キーボードのみで全ての操作が完了できる

  @performance
  Scenario: OTP検証のレスポンス時間
    Given MFAが有効化済みのユーザーがいる
    When メールアドレス "test.user@example.com" とパスワード "SecurePass123!" でログインを試行する
    And 有効なOTP "123456" を入力する
    And "ログイン" ボタンをクリックした時刻を記録する
    Then OTP検証とログイン完了までの時間が3秒以内である
    And ダッシュボード画面の読み込みが完了する

  @backup-codes
  Scenario: バックアップコードの生成と使用
    Given ユーザーがログイン済みである
    When MFAを有効化する
    And "バックアップコードを生成" ボタンをクリックする
    Then 10個のバックアップコード(各8桁)が表示される
    And "これらのコードを安全な場所に保存してください" の注意書きが表示される
    And "印刷" ボタンが表示される
    
    When 一度ログアウトする
    And メールアドレス "test.user@example.com" とパスワード "SecurePass123!" でログインを試行する
    And "バックアップコードを使用" リンクをクリックする
    And 生成されたバックアップコード "ABCD1234" を入力する
    And "ログイン" ボタンをクリックする
    Then ログインが成功する
    And 使用したバックアップコードが無効化される
    And "バックアップコードを1つ使用しました。残り9個です" の通知が表示される

その違いは一目瞭然でした。

  • 網羅的な観点 従来のテストが正常系と一部の異常系のみだったのに対し、セキュリティ(試行回数制限とアカウントロック)、ユーザビリティ(入力フィールドの操作性)、パフォーマンス(レスポンス時間)、具体的なエラーケース(期限切れOTP、使用済みOTP)など、QAエンジニアならではの多角的な観点が網羅されていました。

  • テストの体系化 @smoke, @critical, @regression, @security といったタグが体系的に付与されており、テストの重要度や目的が一目でわかります。これにより、必要なテストだけを選択して実行するなど、効率的なテスト運用が可能になります。

  • ユーザー体験への配慮 「OTP入力フィールドに自動でフォーカスが当たるか」「通知メールの内容は適切か」といった、機能仕様書には現れにくい、しかしユーザー体験に直結する項目までテストシナリオに含まれていました。

QAエージェントは、実装者の視点だけでは「死角」となっていた無数のシナリオを、実装が始まる前に「達成すべきゴール」として明確に定義してくれました。

まとめ:複数のAI人格との「チーム開発」がもたらすもの

実装担当のAIに、「QA専門エージェント」というパートナーを組ませることで、単なる開発生産性の向上だけでなく、以下の大きな恩恵を得ることができました。

  • 開発プロセスの健全化 「何を達成すべきか(ゴール)」を定義する役割と、「それをどう実現するか(実装)」を担う役割を分離することで、健全なテストファースト開発を実践できます。

  • チーム全体の学習 QAエージェントが生成する高品質なテストシナリオは、QA専門でない私たちにとっても非常に勉強になり、チーム全体の品質意識向上に貢献します。

AIを単一のスーパーエンジニアとして扱うのではなく、それぞれの専門性を持った複数のAI人格を「チームメンバー」として役割分担させることで、想像以上の化学反応を観測することができました。

今後の課題と展望

とはいえ、現状ではエージェントの設定が不十分なのか、QAエージェントが持つコンテキストがブラックボックスのように見えづらく、どこまでコンテキストを共有し、どこから明確に切り離されているかを掴みきれていないという課題があり、本格的な採用にはもう少し調整が必要そうです。

ただ、Claude Codeのサブエージェント機能は、複数の視座を持って開発を進めるという、本来あるべきチーム開発の姿に近づけるために有用な機能だと感じています。AI活用におけるリスクを低減させる可能性を秘めているという意味でも、バランスの取れたQAエージェントをチームの一員として迎え入れるべく、今後も試行錯誤を重ねていきたいと考えています。