AIコーディングを活用したフロントエンドテスト推進の取り組み

こんにちは、フロントエンドエンジニアの raraya です。 こちらの記事 でも触れておりますが、弊社では AIコーディング を活用しながら開発を進めています。 今回はその実践例として、フロントエンド領域におけるテストコード整備をAIで効率的に推進する取り組み をご紹介します。

補足:本記事では考え方・方針を中心に紹介します。 AIコーディングのプロンプトや、Vitest / ESLint / SonarJS の細かい設定方法など、具体的な手順には触れていません。 これらの詳細は公式ドキュメントや各種記事をご参照ください。

背景

これまで弊社では、開発者による STG 環境での検証やドッグフーディングに加え、QA チームによる検証を通じてUI の不具合を早期に検知し、本番環境への致命的な不具合流出を最小限に抑えてきました。

しかし、QA チームは本来の専門業務に専念する必要があるため、検証に多くのリソースを割くことは適切ではありません。そのため、開発者自身が責任をもって品質保証を行う体制に移行しました。従来の STG 検証だけでは既存機能の劣化(デグレード)を十分に防げず、特にフロントエンドのコンポーネントテストカバレッジが現状 十分でないこともあり、テストコードの拡充が急務となっています。

さらに、新機能の開発増加や、バックエンド担当者やアルバイトメンバーのフロントエンド参画増に伴い、デグレを発生させず安心して開発できる環境の整備も必要になっています。

現状と目標

この取り組みは 2025年7月に本格始動。 当初のカバレッジは 社内のBEのカバレッジと比べると低い状態でしたが、継続的な整備により 2025年8月21日時点で 大幅に改善しています。

直近の目標は 年内に 60% のカバレッジを達成すること です。

ここでいうテストカバレッジとは、テストによって実際に実行されたコードの割合 を指します。測定には Vitest を用いて Statement Coverage(各コード行が実行されたかどうか) を算出しています。

一見すると 60% は低く見えるかもしれませんが、Google のガイドライン では 「60% は十分許容できる水準」 とされています。 過度に高いカバレッジはコストに見合わないことも多いため、まずは実効性ある 60% を第一目標とするのが現実的と判断しました。

推進方針

テストコードの作成には CursorClaude Code などの AI コーディングツールを活用しています。 これにより、定型的な実装はAIに任せ、人間はレビューなどに集中する 体制を整えています。

基本方針はまず 「質より量」。テストを書く文化を根付かせ、カバレッジの底上げを優先。 そのうえで 60% を達成した後は、「重要ファイルへの重点的なテスト追加」 へとフェーズを移行する計画です。

重点対象の選定基準

60% 達成後も無計画にテストを増やすと、価値の低いテストが量産されかねません。 そこで QA チームの助言をもとに、複雑度 × 更新頻度 × 機能重要度 の3軸で優先度を決定する仕組みを採用予定です。

複雑度の測定

現状でも複雑度の高いファイルを抑制するため SonarJS を導入し、ネストや分岐の多さをスコア化。一定値を超えると Lint エラーとしています。

ただし現在はデフォルト値(15)に対して 30 と緩い設定 にしています。

// eslint.config.js
'sonarjs/cognitive-complexity': ['error', 30] // デフォルトは 15

更新頻度の測定

更新頻度は git log を用いて、過去 2 年間の変更回数を集計。 その結果からリスクの高いファイルを抽出しています。

git log --since="2 years ago" --name-only --pretty=format: \
| grep -E '\.vue$|\.ts$' \
| grep -v 'config/i18n' \
| grep -v '/enums' \
| grep -v '^xxxxx/' \
| sort | uniq -c | sort -nr | head -n 100

(例)

 188 xxxxx/main/sample-project/views/dialogs/components/UiMockDialog.vue
 107 xxxxx/main/demo-app/views/dialogs/components/UiTestComponent.vue
 106 xxxxx/main/sample-project/views/dialogs/components/MockDialog/UiMockDialog.vue
 ...

注意点

私たちのプロジェクトでは Vue2 → Vue3 移行のタイミングで ファイルを一新しているため、上記の単純な「更新回数集計」でも実態と大きな乖離はありません。 しかし、一般的なプロジェクトでこの手法をそのまま用いると以下の点で誤差が生じる可能性があります。

  • ファイルの生存期間を考慮しないと不公平になる 直近で新しく作られたファイルは短期間でも更新回数が多くなりがち。

  • 変更行数の大小を区別できない 1行修正しても500行修正しても1 commit「1回更新」と扱われるため、こちらの方が精度に与える影響は大きいです。

そのため、同様のアプローチを試す場合は、上記のような点を考慮して補正(生存期間で割る、更新回数ではなく「変更行数の合計」や「平均変更行数」)を検討すると、より実態に即した更新頻度が測定できるかと思います。

優先度の算出

最終的には以下を掛け合わせて優先度を算出します。

複雑度 × 更新頻度 × 機能重要度

機能重要度は GA を用いて、メインページなど利用頻度の高い領域を分析。 これにより、投資効果の高い領域から計画的にテストを整備できる体制を整えています。

複雑度指標の補足

SonarJS の Cognitive Complexity 以外にも、ESLint の Cyclomatic Complexity など複数の指標があります。 両者は異なる観点を評価するため、併用することでテスト対象の優先度をより精緻に決定可能 です。

Cognitive Complexity(SonarJS)

  • 人間の認知負荷 を評価する指標
  • ネストや分岐の深さによる「理解しづらさ」を数値化
  • 値が大きいほどメンテナンスリスクが高い

Cyclomatic Complexity(ESLint / Lizard)

  • 技術的な分岐の複雑さ を測定する伝統的指標
  • 必要なテストケース数やバグ混入リスクの推定に有効

段階的な閾値設定

テスト拡充にあわせて複雑度の高いファイルを減らす取り組みも進める予定です(まだ未着手)。 まずは緩やかな閾値を設定し、整備の進捗に応じて段階的に引き締めていく運用を計画しています。

{
  // フェーズ1
  'complexity': ['warn', 20],
  'sonarjs/cognitive-complexity': ['error', 30],

  // フェーズ2
  'complexity': ['error', 20],
  'sonarjs/cognitive-complexity': ['error', 25],

  // フェーズ3
  'complexity': ['error', 10],
  'sonarjs/cognitive-complexity': ['error', 15],
}

参考資料

まとめ

これまでの STG 検証やドッグフーディングだけでは、既存機能の劣化(デグレ)を十分に防ぐことは難しくなっていました。そこで、開発者が主体となって品質保証を行う体制に移行し、テストコードの整備を急務としました。

AI コーディングの活用により、膨大な工数がかかるフロントエンドテストの作成を効率化。まずは カバレッジ 60% の達成 を目指し、その後は 重要領域への重点的なテスト追加とリファクタリング を進めることで、デグレを防ぎつつ安心して開発できる体制を構築していきます。