---
title: "AIが書いたコードのテスト：いつも緑のテストを避ける"
url: https://www.thinnd.site/ja/gijutsu/ai-ga-kaita-code-no-test-tsuneni-midori-wo-sakeru/
language: ja
author: "Nhu Duy Thin (Thinnd)"
published: 2026-10-29
updated: 2026-10-29
section: "エンジニアリング"
tags: ["テスト", "AI", "ミューテーションテスト", "プロパティベーステスト", "品質"]
summary: "AIがコードとテストの両方を書くと、テストは要件でなく、書いたばかりのコードに合わせがちで、不具合を捉えないまま緑になります。高いカバレッジでも足りません：ミューテーションに導かれたテスト生成の論文は、カバレッジ100%でもミューテーションスコアは約4%というテストスイートに触れています。テストの価値を保つ7つの方法：コードでなく仕様からテストを書く、直す前にテストが失敗するのを見る、自分でコードを壊してテストが赤になるか見る、ミューテーションテスト、プロパティベーステスト、境界値の表、一度実際に動かす。"
license: "Cite with the author name and the canonical URL above."
---

# AIが書いたコードのテスト：いつも緑のテストを避ける

> AIが関わるコードを書く人、レビューする人のための記事で、初心者も対象です。技術用語には短い説明を付けます。
>
> コードの例とその数字は、イメージしやすいように**作り直した**ものです。「カバレッジ100%、ミューテーションスコア4%」は、論文の要旨から取りました（全文は読んでいません）。名前を挙げたツールは例にすぎず、動かしていません。方法は**私の提案**です。

---

## 先に要点

- **AIがコードとテストの両方を書く**と、テストは要件でなく、コードを確認するだけになりがちです。
- **緑のテストでは足りません。** 高いカバレッジでも足りません：100%を覆っても、ほとんど不具合を捉えないスイートがあります。
- 正しい問いは「テストは緑か」ではなく、**「コードが間違っていたら、テストは赤になるか」**です。
- **7つの方法**：仕様から書く、先に赤を見る、自分で壊す、ミューテーションテスト、プロパティベース、境界値の表、実際に動かす。
- 最も安いことから：**手でコードを壊して**、テストを見る。

---

## むずかしい言葉をやさしく

| 用語 | やさしい意味 |
|---|---|
| **テスト** | 別のコードを動かし、結果を期待と比べるコード。 |
| **カバレッジ** | テストが通るコードの行の割合。テストが正しく確かめているかは言わない。 |
| **ミューテーションテスト** | コードをわざと少し壊して、テストが赤になるか見ること。 |
| **ミューテーションスコア** | 壊した版のうち、テストが捉えた割合。 |
| **プロパティベーステスト** | いくつかの例の代わりに、常に成り立つ規則を述べ、ツールに多くの入力を試させる。 |
| **境界値** | 規則の境目にちょうどある値。たとえばちょうど50万。 |
| **いつも緑のテスト** | コードが間違っていても、決して失敗しないテスト。 |

---

## 1. 問題：テストを書く人が、コードも書いた人

1人がコードを書いてからテストを書くとき、たいてい**同じ理解を両方に持ち込みます**。要件を誤解したなら、コードは間違い、テストも一緒に間違うので、緑になります。AIでは、さらに起きやすい：AIは**コードができた後に**テストを書き、そのコードが見えているので、テストはコードがしていることに合わせて作られがちです。

だから[AIが書いたコードのレビューの15項目](https://www.thinnd.site/ja/gijutsu/ai-ga-kaita-code-no-review/)には、テストについての2つの項目があります：テストは大事なことを確かめているか、そしてAI自身が書いたテストは、コードを壊して赤になるか見ること。

これは単なる感覚ではありません。言語モデルでミューテーションに導かれてテストを生成する論文（MutGen、2025年）は、**カバレッジは不具合検出の弱い指標**だと論じ、**カバレッジ100%でも、ミューテーションスコアは約4%**というスイートに触れています。私は要旨を読んだので、この数字は、一般的な統計でなく、問題を示す例として扱ってください。

---

## 2. 例：50万の境界

*作り直した例。* 要件：**50万以上の注文は10%引き。**

AIが書いたもの：

```js
function discount(total) {
  return total > 500000 ? total * 0.9 : total;
}

test("大きな注文は10%引き", () => {
  expect(discount(600000)).toBe(540000);
});

test("小さな注文は割引なし", () => {
  expect(discount(100000)).toBe(100000);
});
```

2つのテストとも緑で、カバレッジは100%。でもコードは間違っています：要件は「50万**以上**」なのに、コードは`>`を使っているので、**ちょうど500,000**の注文が割引されません。

**手で壊す。** `>`を`>=`に変える。つまり、コードを要件に**合うよう直す**のです。テストを動かし直す：**まだ緑**。つまり2つのテストは、境界で、間違ったコードと正しいコードを見分けられません。これを「生き残った変異体」と呼びます。

**仕様からテストを1つ足す：**

```js
test("ちょうど500,000は割引される", () => {
  expect(discount(500000)).toBe(450000);
});
```

これは、今のコードでは**赤**で、直した後は緑です。価値のあるテストです：**コードが間違っているとき失敗する**のですから。

---

## 3. テストの価値を保つ7つの方法

### 方法1：コードでなく仕様からテストを書く

コードでなく**要件**を見て、例を書きます。記事[仕様駆動開発](https://www.thinnd.site/ja/gijutsu/spec-kudo-kaihatsu-shiyosho-wo-saki-ni/)は、変わったケースも含め、受け入れられる例を3〜6個、先に書くことを勧めます。それがまさに、必要なテストです。

AIにテストを書かせざるをえないなら、コードだけでなく、**仕様と例**を渡してください。

### 方法2：先にテストが失敗するのを見る

直す**前に**テストを書き、動かし、**正しい理由で失敗するのを見て**、それから緑に直します。一度も赤を見ていないテストは、何かを捉えられるか分からないテストです。

Anthropicの実践ガイドは、エージェントへの依頼の例で、まさにこの考えを使っています：「再現する失敗するテストを書き、それから直して」。

### 方法3：自分でコードを壊す

最も安い方法で、ツールは要りません。テストが緑になった後、**コードをわざと少し壊して**、動かし直します：

- `>`を`>=`に、またはその逆に変える。
- `0.9`を`0.8`に変える。
- 条件を1つ消す、または`&&`を`||`に変える。
- 固定の値を返す。

テストが緑のままなら、テストが確かめていない場所を見つけたことになります。それから変更を元に戻します。

### 方法4：自動のミューテーションテスト

方法3がすることを、体系的に行います：ツールが多くの小さな壊れた版を作り、どれが**生き残る**か（テストが捉えなかったか）を報告します。言語ごとにツールがあり、たとえばStryker（JavaScript）、mutmut（Python）、PIT（Java）。調べる手がかりとして挙げるもので、この記事で動かしたわけではありません。

注意：ミューテーションテストは**遅く**、重要でない生き残りを多く報告することがあります。プロジェクト全体でなく、重要な中核に使ってください。

### 方法5：プロパティベーステスト

いくつかの例の代わりに、**常に成り立つ規則**を述べ、ツールが多くのランダムな入力を試します。割引の関数なら：

- 結果は、元の合計より**決して大きくならない**。
- **50万以上**のすべての合計で、結果はちょうど90%。
- **50万未満**のすべての合計で、結果は合計と等しい。

Hypothesis（Python）やfast-check（JavaScript）のようなツールがこれをします。思いつかなかった境界値を見つけることがよくあります。

### 方法6：境界値の表

閾値のある規則ごとに、**3つの値**を書きます：すぐ下、ちょうど、すぐ上。

| 入力 | 期待 |
|---|---|
| 499,999 | 499,999（割引なし） |
| 500,000 | 450,000（割引） |
| 500,001 | 450,000.9（割引） |

さらに変わったケース：0、負の数、非常に大きい、型違い、空。

### 方法7：一度実際に動かす

単体テストは、**開いて試す**ことの代わりになりません。記事[AIエージェントと働いた3時間](https://www.thinnd.site/ja/genba-noto/ai-agent-jissai-no-purojekuto-nikki/)には、論理の検査が捉えられなかった不具合があります。人の目に見えるものだからです。アプリを動かし、主な経路を触り、見たことを記録してください。

---

## 4. 弱いテストの匂い

AIが書いたテストをレビューするとき、次の兆候を探します：

| 兆候 | なぜ弱いか |
|---|---|
| **検査がない**（`expect`や`assert`がない） | 行を通るだけで、結果を比べない |
| **当たり前を確かめる**（結果が空でない、型が合う） | ほとんど常に真 |
| **結果を自分自身と比べる** | 常に真で、何も検出しない |
| **すべてをモックして**、モックが呼ばれたと確かめる | モックを試すだけで、振る舞いは試さない |
| **現在の出力を答えとして保存する** | 既存の不具合がすべて「正しい」になる |
| **エラーを捕まえて飲み込み**、緑と報告する | 失敗を隠す |
| **1つのきれいな値だけ試す**（600,000のような） | 境界と変わったケースを見逃す |
| **コードと同じ式で期待値を計算** | 同じ間違いは、一緒に通る |

どのテストも、答えられるべきです：**「どんな間違ったコードなら、これは赤になるか」**。

---

## 5. AIが書いたテストをレビューする6つの問い

1. テストは、**仕様から**書かれたか、コードから書かれたか。
2. 少なくとも一度、**失敗するのを見た**か。
3. **コードを少し壊す**と、テストは赤になるか。（大事な所で、少なくとも一度試す。）
4. すべての閾値に**境界値の表**があるか。
5. **本当の検査**（通るだけでない）があり、**余計なモックがない**か。
6. アプリの主な経路を**実際に動かした**か。

---

## 6. AIにテストを頼むときの頼み方

*私の提案です。* 「この関数のテストを書いて」の代わりに、こう試します：

> 「これが仕様と、受け入れられる3つの例（上の例）。仕様からテストを書いて、**今あるコードからではなく**。各閾値のすぐ下、ちょうど、すぐ上の値を含めて。そのあと、**コードを3通りにわざと壊して**、どのテストが赤になるか教えて。動かしたコマンドと出力を見せて。」

最後の依頼は、エージェントが**自分で確かめる**方法でもあり、記事[エージェントへの依頼を書くときの7つの間違い](https://www.thinnd.site/ja/keiken/agent-eno-irai-no-shippai-7tsu/)のとおりです。

---

## 7. バランスの取れた見方

- **この記事の数字は断片にすぎません。** MutGenの論文は全文を読んでおらず、このプロジェクトのAI製コードについての私自身の測定もありません。
- **ミューテーションテストは時間がかかります。** 選んで使い、100%のスコアを追わないでください。
- **テストだけではありません。** コードレビュー、公開後の不具合の監視、実際に動かすことも要ります。
- **良いテストにも保守の費用があります。** 細かいテストが多すぎると、コードを変えるのが遅くなることがあります。
- **50万の例は作り直したもの**ですが、不具合の種類（境界での間違い）は、とても現実的で、よくあるものです。

---

## 8. 結論

緑のテストが言うのは、**テストとコードが互いに一致している**ことだけで、両方が正しいことではありません。AIが両方を書くと、その一致は、同じ誤解から生まれやすい。問う価値のあるのは、**「コードが間違っていたら、テストは赤になるか」**で、知る最も安い方法は、コードを壊して見ることです。

今日の小さな一歩：AIが書いたテストのある重要な関数を1つ選び、その中の比較の記号か数字を1つ変えて、テストを動かし直してください。緑のままなら、書くべき最初のテストを見つけたことになります。

---

## 参考資料

- [On Mutation-Guided Unit Test Generation (MutGen)、arXiv:2506.02954](https://arxiv.org/html/2506.02954v2)
- [Anthropic：Best practices for Claude Code](https://code.claude.com/docs/en/best-practices)
- ブログ内の関連記事：[AIが書いたコードのレビュー](https://www.thinnd.site/ja/gijutsu/ai-ga-kaita-code-no-review/)、[仕様駆動開発](https://www.thinnd.site/ja/gijutsu/spec-kudo-kaihatsu-shiyosho-wo-saki-ni/)、[エージェントへの依頼を書くときの7つの間違い](https://www.thinnd.site/ja/keiken/agent-eno-irai-no-shippai-7tsu/)、[AI機能のための評価を書く](https://www.thinnd.site/ja/gijutsu/ai-kinou-no-evals-30-no-jissai-no-jirei/)
