【ファインディ株式会社】そのテスト、バグっても気づけません【Human in the loop? Human on the loop? meetup】

1K Views

August 31, 26

スライド概要

ファインディ株式会社
Human in the loop? Human on the loop? meetup

のLT資料です。

https://findy-aiplus.connpass.com/event/401925/

profile-image

エンジニア。スクラムマスター。 Zennでサーバーレス本書いてます。 http://zenn.dev/mistletoe/books/93f5810c20eb9a http://github.com/theMistletoe http://zenn.dev/mistletoe http://qiita.com/mistletoe http://note.com/themistletoe

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

#HUMANONTHELOOP ・ 2026. 08. 31 そのテスト、 バグっても気づけません 〜 AIが書いたテスト、本当に意味のあるテストになっていますか 〜 Motoaki Tanaka @mot0aki

2.

自己紹介 Motoaki Tanaka X: @mot0aki ▸ 株式会社レッドジャーニー ソフトウェアエンジニア アジャイル開発推進 新規プロダクト開発・プロダクトマネジメント 生成AI開発・導入支援 AIカタリスト @mot0aki ・ Human in the loop? Human on the loop? meetup 2

3.

AI駆動開発ではハーネスが大事 AIも人も、どんどんコードを書く ▼ 壊れたまま進まないよう、ハーネスで受け止める 型・Lint 書いた時点で弾く 自動テスト 壊れたら気づく CI/CD 出す前に止める ハーネス 人が全部見るのをやめられるのは、このハーネスが効いているからです。 @mot0aki ・ Human in the loop? Human on the loop? meetup 3

4.

自動テスト 実装した機能が想定通り動くことを、簡単に担保できる そして最近は、テストコードもAIに書いてもらうようになってきました。 @mot0aki ・ Human in the loop? Human on the loop? meetup 4

5.

では、あなたのプロダクトは 十分にテストできていますか? @mot0aki ・ Human in the loop? Human on the loop? meetup 5

6.

1つの目安 → カバレッジ 実装コードのうち、どのくらいテストできているかを示す指標 @mot0aki ・ Human in the loop? Human on the loop? meetup 6

7.

カバレッジが見せているのは「実行されたか」だけ カバレッジが見ているもの 実装コード → テストを実行 → 通った = この行は実行された カバレッジでは見えないもの 実装コードを壊す → テストを実行 → やっぱり通った = 壊れても気づけない そのテストコードが、バグを埋め込んだときに気づけるテストになっているかは分かりません。 @mot0aki ・ Human in the loop? Human on the loop? meetup 7

8.

AIが書いてくれたそのテストコード、 本当に意味のあるテストになっています か? @mot0aki ・ Human in the loop? Human on the loop? meetup 8

9.

実装を壊してもテストは通ってしまう 実装 / isAdult.ts >= の = を1文字消してみる return age >= 18; // isAdult(18) → true return age > // isAdult(18) → false 18; テスト / isAdult.test.ts 境界から離れた値しか見ていないテスト (カバレッジは100%) expect(isAdult(25)).toBe(true); もし 18歳の扱いは変わる。でも18歳以外の結果は1つも 変わらない。 expect(isAdult(16)).toBe(false); 結果 25も16も >= と > で答えが同じなので1本も落ち ない。 テストはある。実行もされている。それでも壊れたことに気づかない。 @mot0aki ・ Human in the loop? Human on the loop? meetup 9

10.

02 そこで導入してみたのが MutationTest ミューテーションテスト ── テストが「気づけるか」を機械的に確かめる @mot0aki ・ Human in the loop? Human on the loop? meetup 10

11.

MutationTest = わざと壊してテストを走らせる ▶ 実装コード 1か所だけ 機械的に書き換える Mutant ▶ 既存のテストを そのまま走らせる ▶ 落ちた → Killed 通った → Survived 例) if (price > 1000) → if (price >= 1000) // 境界をずらす if (isAdmin) → if (true) // 条件を常に成立させる msg = "saved" → msg = "" // 文字列を空にする この書き換え1つが Mutant。1ファイルでも数十〜数百個が自動でつくられます。 @mot0aki ・ Human in the loop? Human on the loop? meetup 11

12.

落ちれば Killed、通ってしまえば Survived Killed テストが落ちた 壊したことに気づけた。テストが効いている証拠。 Survived テストが通ってしまった 壊しても誰も気づかない。ここが実質の穴。 Mutation Score = Killed ÷ Mutant数 テストが気づけた割合 カバレッジは実行されたか、Mutation Score は壊れたときに気づけるかを見ます。 変異ごとにテストを回すため実行時間は長い。まずは1ファイルに絞るのが現実的です。 @mot0aki ・ Human in the loop? Human on the loop? meetup 12

13.

国内にも実践例がある 01 AIが書いたテストを 検証する LLMが生成したテストの品質を Mutation Testing で確かめる KAKEHASHI Tech Blog・2026 02 フロントエンドに 導入する JS向けライブラリ Stryker を実戦 導入した記録 Zenn・hitocolor @mot0aki ・ Human in the loop? Human on the loop? meetup 03 テストの十分性を 評価する ミューテーションテストの技法とし て整理されている 豆蔵デベロッパーサイト・2024 13

14.

03 フロントエンドでも 導入しています @mot0aki ・ Human in the loop? Human on the loop? meetup 14

15.

フロントエンドではこのように検知されます @mot0aki ・ Human in the loop? Human on the loop? meetup 15

16.

なぜ生き残ったのか テストが見ていた範囲 ワークスペース一覧 AAA111 質問 3 件 リンクはある・名前も AAA111・件数も合う ───────▶ to={`/${ws.code}`} この矢印だけ 誰も見ていなかった ワークスペース詳細 /AAA111 を空にしてもリンクは消えず、一覧ページ自身を指すだけ。role も表示名も変わらないので、テストは通ってし まいます。 to @mot0aki ・ Human in the loop? Human on the loop? meetup 16

17.
[beta]
テストを修正(足りないケースを追加)
// フロントエンドのテストコードの例
it('一覧のリンクをクリックするとそのワークスペースのページへ遷移する', async () => {
renderWithProviders(
<Routes>
<Route path="/workspaces" element={<MyWorkspacesPage />} />
<Route path="/:code" element={<WorkspacePage />} />
</Routes>,
{ initialEntry: '/workspaces' },
);
// AAA111 をクリックしたら
await user.click(await screen.findByRole('link', { name: /AAA111/ }));
// AAA111 のページが表示されていることを確認
expect(await screen.findByTestId('ws-code')).toHaveTextContent('AAA111');
});

@mot0aki ・ Human in the loop? Human on the loop? meetup

17

18.

修正されたことが確認できた 76行目の Survived が消え、 Killed になりました! @mot0aki ・ Human in the loop? Human on the loop? meetup 18

19.

プロダクトでは2段構えで回しています ① 実装中 ── Hooks で自動実行(対象は変更差分のみ) エージェントが実装 → 差分に MutationTest → Survived → サブエージェントが検証・修正 ② PR作成時 ── CI でチェック PR を作成 → CI でも MutationTest → 見逃しを人間が検知 まずエージェントのループ内で自動修正し、すり抜けた分は PR の CI で人間が気づけるようにしています。 @mot0aki ・ Human in the loop? Human on the loop? meetup 19

20.

実行スコープとリードタイムのトレードオフ MutationTest は変異の数だけテストを回すので、実行時間はどうし ても長い スコープ広め スコープ狭め そのぶん実行時間が伸びて、エージェントのループが止 まる そのぶん見える範囲は狭くなる 見つけられる穴は増える 結果がすぐ返ってくる 実行スコープは「その場面でどれだけ待てるか」から決める 速さが要る場面ほど、スコープを絞る @mot0aki ・ Human in the loop? Human on the loop? meetup 20

21.

MutationTestで 空虚なテストを減らしていこう! @mot0aki ・ Human in the loop? Human on the loop? meetup 21

22.

ご清聴ありがとうございました。 @mot0aki @mot0aki ・ Human in the loop? Human on the loop? meetup