25
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

初めてのバグ分析でGemini先生に壁打ちを頼んだ話

25
Last updated at Posted at 2025-12-18

はじめに

株式会社LITALICOでQAチームに所属している@k_kitamuraと申します。
今年もアドカレの記事を書いていきますのでよろしくお願いします。
現在私は担当しているプロダクトのQAチームのリーダーをやっておりまして、月次リリースのテスト担当以外にプロダクトの品質向上のためバグ分析を始めました。
具体的には

  • 起票されたissueを月ごとに集計し、バグの混入時期や発見タイミング(顧客指摘なのか、開発・QAテストでの発見なのか)、顧客影響度をグラフ化
  • 月次リリースのバグ密度やテスト密度を計算して考察

などをおこない、今後の品質保証プロセスの最適化を検討しています。

分析自体はやりがいがあるのですが、正直なところ自分の分析スキルはまだ拙い部分も多く自信がありません。
issueを月ごとに集計してグラフを作っても、なかなか気づきを得られず手が止まってしまうこともしばしばです。
そんな時ふとAIに聞いてみようかという考えにいたり、Googleの生成AI「Gemini」を壁打ち相手として頼ってみることにしました。

今回は普段使いのようにGeminiと対話する方法でやっていきました。
もし別の活用方法などがあれば教えていただけるとありがたいです。

まずは集計に向けての準備と集計作業

以下に添付しているグラフやバグ密度などの数値は仮のものです。

準備としてまずスプシにissueを並べていくのですが、引っ張ってくる方法をGeminiに聞いてみました。
自分で決めた項目名とそれに該当するissueから引っ張ってきてほしい情報を伝えると↓にあるGASを作ってくれました。

Geminiが作成したもの(一部加工済)
バグissue取得くん
/**
 * 指定されたGitHubリポジトリから特定のラベルが付いたIssueを取得し、
 * スプレッドシートに書き出すスクリプトです。
 * 表示順やフォーマットをカスタマイズしています。
 */
function getGitHubIssuesByLabel() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  
  // シート全体をクリアする代わりに、2行目以降をクリアします。
  // これにより、1行目にタイトルなどを入れても消えなくなります。
  if (sheet.getLastRow() >= 2) {
    sheet.getRange(2, 1, sheet.getLastRow() - 1, sheet.getMaxColumns()).clearContent();
  }

  // --- 設定項目 ---
  const owner = ""; // GitHubのオーナー名
  const repo = "";          // GitHubのリポジトリ名
  const label = "";      // 絞り込みたいラベル名
  const perPage = 100;                 // 1ページあたりの取得件数(最大100)
  const maxPages = 10;                 // 取得する最大ページ数
  const targetYear = 2025;             // 取得対象の年(西暦)
  const targetMonth = 6;               // 取得対象の月(1~12)
  
  // 重要:セキュリティのため、トークンはスクリプトプロパティに保存することを強く推奨します。
  const token = ""; // あなたのGitHub Personal Access Token

  const headers = {
    'Authorization': `token ${token}`
  };

  const options = {
    "headers": headers
  };

  // スプレッドシートのヘッダー行をご要望の順序に変更
  const titles = [
    "番号", "不具合内容", "QAテスト対象", "発見日時", "発見プロセス", 
    "混入年月", "顧客影響度", "発生頻度", "リスクレベル", "プロセス", 
    "フォーマット", "オペレーション", "備考"
  ];
  
  // --- ここから変更点です ---
  // ヘッダーを1行目ではなく、2行目に書き込みます。
  sheet.getRange(2, 1, 1, titles.length).setValues([titles]);

  let allIssuesData = [];
  // ページネーションで複数ページのIssueを取得
  for (let page = 1; page <= maxPages; page++) {
    const url = `https://api.github.com`;
    const response = UrlFetchApp.fetch(url, options);
    const issues = JSON.parse(response);

    if (issues.length === 0) {
      break; // 取得するIssueがなくなったらループを終了
    }

    const issuesForPage = issues
      .filter(issue => {
        // Pull RequestではないIssueのみを対象
        if (issue.pull_request) {
          return false;
        }
        // 作成日時でフィルタリング
        const createdAt = new Date(issue.created_at);
        return createdAt.getFullYear() === targetYear && createdAt.getMonth() + 1 === targetMonth;
      })
      .map(issue => {
        // 発見日時を「yyyy/MM/dd HH:mm」形式にフォーマット
        const discoveredAt = Utilities.formatDate(new Date(issue.created_at), "JST", "yyyy/MM/dd HH:mm");
        
        // スプレッドシートに出力する形式にデータを整形
        return [
          `=HYPERLINK("${issue.html_url}", ${issue.number})`, // 番号
          issue.title,        // 不具合内容
          "",                   // QAテスト対象
          discoveredAt,         // 発見日時
          "",                   // 発見プロセス
          "",                   // 混入年月
          "",                   // 顧客影響度
          "",                   // 発生頻度
          "",                   // リスクレベル
          "",                   // プロセス
          "",                   // フォーマット
          "",                   // オペレーション
          ""                    // 備考
        ];
      });
    
    allIssuesData.push(...issuesForPage);
  }

  // 収集したデータをシートに一括で書き込み
  if (allIssuesData.length > 0) {
    // --- ここから変更点です ---
    // データをヘッダーの下(3行目)から書き込みます。
    sheet.getRange(3, 1, allIssuesData.length, allIssuesData[0].length)
         .setValues(allIssuesData);
  }
}

あとはこれをスプシの拡張機能に載せて実行することで、GitHubのissueを起票月ごとに並べることができるようになりました。
集計作業は手動だったので詳細は省きますが、月ごとのissueに対して発見工程やリスクレベルなどを調査し、スプシに記載していきました。
その情報をもとにして顧客指摘VS内部検出の件数と割合を表した円グラフや、
顧客指摘VS内部検出の件数と割合.png

発見工程ごとの顧客影響度を比較する棒グラフなどを作成しました。
発見工程ごとの顧客影響度比較.png

集計はできた、けれど…。「で、ここから何が言えるの?」の壁

グラフを作ったあと、最初の壁に直面しました。
それは「集計はできても、そこから有意義な考察が引き出せない」という壁です。

Issueを月ごとに集計し、グラフ化するところまでは順調でした。
しかし、そのグラフを前にして、
「数字は出た。グラフもできた。……で、ここから何が言えるんだ?」
と手が止まってしまう事態に陥りました。
現状の可視化はできても、そこから「どんな問題が潜んでいるのか」「次はどうすべきか」というネクストアクションに繋がる「分析」が思い浮かばないのです。

自分一人で考えても、「今月はちょっと多かったな」くらいの感想で止まってしまい、品質保証プロセスを最適化するための深い洞察に至ることができませんでした。

Gemini先生に「丸投げ」してみる

そこで、私はGeminiに聞いてみることにしました。
きっかけはグラフのスクショを送って分析とかできるのかなという疑問からだったと思います。
「グラフを添付するので、分析と問題点を出してほしい」
グラフのスクショを添付して上記の文を投げかけると、Geminiはグラフの数値の増減や傾向を読み取り、いくつかの観点を提示してくれました。
内容としても大きくズレてはいなさそうだったので、追加でより具体的な分析を依頼していきました。

  • 期間を指定して深掘りする:「4月~6月を通しての課題を教えて」と期間を区切ってトレンドを聞いてみる
自分「4月~6月を通しての課題を教えて」
4月~6月期の総括
この3ヶ月間で、品質状況は以下のように変化しました。

1. 顧客への影響:課題が「量」から「質」へ
顧客に届く不具合の件数は、4月の61.5%から6月には3.7%へと劇的に減少しました。これは大きな成果です。
しかし、万が一顧客へ流出してしまった際の不具合の影響度は依然として高く(平均3.0)、最も深刻なバグをいかに防ぐかという「質」の保証が新たな焦点となっています。

2. 内部検出プロセス:事後的な対応へのシフト
内部での検出タイミングが、QAテストなどの「事前」の工程から、エラーログによる「事後」の工程へシフトしています。
これは、テストシナリオが複雑なユースケースをカバーしきれていない可能性を示唆しており、開発の手戻りコストが増大する懸念があります。

3. 根本原因:上流工程の課題が継続
3ヶ月を通して、不具合の根本原因は一貫して**「仕様関連の不備」**にあります。これが下流での確認漏れや事後検出を引き起こす元凶です。

  • 別の指標を掛け合わせる: 単純な件数だけでなく、「バグ密度」や「テスト密度」のデータを加えて再分析を依頼する
自分「4月のバグ密度は0.44[件/KLOC]であり、テスト密度は513.4[件/KLOC]だった。この内容も踏まえて再度分析して」

追加情報からの再分析サマリー
4月と6月の密度データを比較することで、品質課題の核心がより鮮明になりました。

●4月の状況:
・テスト密度(513.4件/KLOC): 異常に高い数値です。これは、コード量に対して膨大な量のテストが実施されたことを示します。
・バグ密度(0.44件/KLOC): テスト量とは裏腹に、バグ密度も非常に高く、コードの品質が低い状態でした。
・結論: 4月は、「テストの量が品質を全く担保できていなかった」月と言えます。
膨大なテストは、おそらく仕様の不備に基づいていたため、重要な欠陥を見逃し、結果として61.5%という高い顧客指摘率につながりました。
これはテストの「量」だけを追求しても意味がないことを示す典型例です。

●6月との比較:
・6月はテスト密度が 1.62 と適正な範囲に落ち着き、バグ密度も 0.01 と劇的に改善しました。
これは、新規開発プロセスにおいて、テストの**「質」、つまり「何をテストすべきか」**が改善されたことを示しています。

この分析から、3ヶ月間の大きなトレンドは**「無駄な量のテストから、有効な質のテストへの転換が進んだこと」、そして新たな課題として「既存資産の品質(回帰テスト)」**が浮かび上がったことだと結論付けられます。

こうして多角的な視点でデータを回していくことで、自分一人では見落としていた切り口が見え始めました。

AI任せにはできない、「舵取り」の重要性

もちろん、全てがスムーズにいったわけではありません。
何度か自分が聞いている部分とは異なる回答をすることも多々ありました。

私が知りたかったのは「その月のリリースにおける品質」だったのですが、Geminiにただ「分析して」と頼むと、どうしても過去から累積している既存不具合を含めた全体傾向に引っ張られた回答が返ってくることが多かったのです。
その場合は都度意図を明確に伝えるよう心がけました。

「過去の不具合ではなく、今回の月次リリースに含まれる不具合に着目して考えてほしい」

このように指示を修正すると、Geminiは私の意図を汲み取り、リリース単位での品質傾向にフォーカスを当ててくれるようになりました。
この経験を通して、いかに正しい文脈を伝えて導くことが重要かを学べたと思います。

意外と頑固なGemini先生

逆に私がGeminiに「救われた」場面もありました。
ある月のバグ密度の数値について考察していた時、私はIPAさんが出しているソフトウェア開発分析データ集2022を参照してこの数値なら中央値を下回っているので悪くはないだろうと判断していたのですが、Geminiは「品質が低い状態」と判断しました。
私は「いやいや、この資料を見るに中央値よりも低いので、決して悪いとは言えないのでは?」と根拠となる資料の情報を伝えて反論しました。
普段の生成AIなら、ユーザーの主張に合わせて「失礼しました、おっしゃる通りです」と意見を変えてきそうな場面ですが、今回のGeminiは折れませんでした。
Geminiは一般的に高品質なソフトウェア開発におけるバグ密度の目標値や、他の月よりもバグ密度が高くなっている件などを挙げて警鐘を鳴らしてきたのです。
後になってこの話を他のメンバーに話したところ、私が参照した値が間違っており、Geminiが示した値が正しいと指摘を受けました。
AIはこちらに話を合わせることが多いイメージがありましたが、データに基づいた客観的な視点を貫いてくれたことで、誤った判断を未然に防ぐことができました。
この事件(?)は今も深く印象に残っています。

おわりに

Geminiとの壁打ちを通じて、私は「分析結果の解釈」に少しずつ自信を持てるようになりました。
一人でグラフとにらめっこしていた時は何も思い浮かばず手が止まりがちでしたが、今では「まずGeminiに投げてみて、そこから対話しながら深掘りする」というフローができています。
スキルに自信がなくても、AIというパートナーがいれば、視点を広げ、時には間違いを正してもらいながら前に進むことができます。
もし私と同じように、新しい取り組みに対して「自分のスキル不足」を感じて足踏みしている方がいたら、ぜひ一度、AIを「先生」や「同僚」だと思って壁打ちを頼んでみてください。
特段難しい操作をせず、ただ思ったことを聞いてみるだけでもそこから新たな視点をくれるとても便利なツールだと思います。

以上、ご覧いただきありがとうございました。

さいごに、この記事は社内の「アドカレ記事の壁打ちサポーター」Gemと相談しながら書き上げました。
素敵なツールを提供してくれたことにこの場を借りて感謝の気持ちを述べたいと思います。
ありがとうございました。

25
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?