---
title: "確かめない技術 第3回：テストを再実行しない技術"
author: garplab
publisher: TypingTube
license: CC BY 4.0
license_url: https://creativecommons.org/licenses/by/4.0/
license_scope: 「CC BY 4.0」の印から始まる節（仕組み・検証手順・コード）。印の無い本文は著作権を留保
canonical: https://typing-tube.net/articles/tashikamenai-03-no-rerun
series: "確かめない技術"
language: ja
---


今回は、テストの再実行の話です。再実行というのは、コードを 1 文字も変えていないのに、同じテストをもう一度走らせることです。AI はこれをよくやります——「通っていることを確認します」「念のためもう一度」。そのたびに私は、結果が変わらないと分かっているものを、最後まで待っていました。

1 作目「読まない技術」の[第 1 回](https://typing-tube.net/articles/cd93e0c5cac832)で、テストの実行の入口をラッパー 1 本にまとめ、全文をログに残したうえで、画面には数行の要約だけを出す形にしました。今回は、その残したログを、再実行の代わりに使います。

まず一つだけ、数えてみてください。AI コーディングエージェントとの直近のセッションで、テストは何回走りましたか。そのうち、**コードを変えた直後ではない実行**——「通っていることを確認します」「念のためもう一度」「報告の前に最終確認」——は、何回だったでしょうか。

AI はよくテストを再実行します。理由は単純で、**AI は結果の確認と再実行を区別しない**からです。人間は「さっき通った」を覚えているか、画面をスクロールして見返します。AI は、結果がコンテキストから流れたら（あるいはセッションが変わったら）、確かめる手段は再実行しかないと考えます。コードが 1 文字も変わっていなくてもです。「区切りではテストで確認する」は、学習された開発の振る舞いでもあります。書き足した 1 行では、この優先順位は覆りません。

コストは時間です。私の環境でテスト全量は 277.85 秒。1 作目 第 1 回で出力は数行の要約になっていますが、**4 分半という時間は 1 秒も減っていません**。確認のための再実行が 3 回あれば、それだけで約 14 分が消えます。おまけに、走っている 4 分半の間に別のセッションがもう 1 本走らせる事故の窓が開きます（これは次回の主題です）。

この連載に出てくる私の環境の数——全量の秒数、テストの件数、走らせていない領域の数——は、2026-09-08 に測ったものです。同じ環境で 2026-09-10 に測り直すと、307.80 秒・14,238 件・23 領域でした。3 つとも仕組みは同じまま動いていて、増えたのはテストの数と、それに連れた時間です。数は日ごとに動くので、比べるときは測った日ごと見てください。

理解したことは一文にできます。

> **AI は結果の確認と再実行を区別しない。前回の結果が読める場所があれば、再実行は起きない。**

## 仕組み: 前回の結果を読める場所にする

1 作目 第 1 回のラッパーは、全出力を毎回 `tmp/test_last.log` に残しています。つまり「確認」に必要なものは、もう手元にあります。足すのは再表示の入口 1 つです。

```bash
# scripts/test.sh へ追記。--last の分岐は log= と mkdir の直後に置く
if [ "${1:-}" = "--last" ]; then
  if [ ! -f "$log" ]; then echo "まだ一度も実行していません" >&2; exit 1; fi
  echo "--- 前回の要約（実行: $(cat "${log}.time" 2>/dev/null || echo 不明) / 全文: ${log}）---"
  grep -E "^Finished in " "$log" | tail -1
  grep -E "^[0-9]+ runs, " "$log" | tail -1
  exit 0   # 何も実行しない。読み直すだけ
fi
date '+%m/%d %H:%M' > "${log}.time"   # 実行する側はここで日時を書き残す（bin/rails test の直前に）
```

そして 1 作目 第 1 回で置いた「素のコマンドを止める hook」の案内文に、1 行だけ足します。

```
結果を見るだけなら: scripts/test.sh --last （再実行せずに前回の要約が出ます）
```

これで経路は閉じます。AI が「確認のため」に素のテストを叩く → hook が止めて案内を出す → 案内に「見るだけなら `--last`」がある → AI は一瞬で要約を受け取り、次の作業へ進みます。私は指示ファイルには何も足していません。**確認したい瞬間の目の前に、読み直す入口を置いた**だけです。

大事な設計が一つ。`--last` の 1 行目には**前回実行の日時**を必ず入れます。「これは 10:41 の結果」と毎回言う。コードを変えたあとにうっかり `--last` で確認しても、時刻の古さが目に入る形にしておきます。

## 待たなくなったもの

確認のためのテスト実行です。4 分半の進捗表示を、私はもう眺めていません。結果は変わらないと分かっているものを待つ時間が、シリーズを通して一番大きい削減です——出力の行数ではなく、**実際に待つ時間**が減ります。

## 注意: `--last` は「変えていない」ときだけの近道

死角ははっきりしています。コードを変えたのに AI が `--last` で確認すれば、古い結果を新しい結果として読みます。守りは二つで足ります。一つは上に書いた日時の常時表示。もう一つは、`--last` を「実行の代わり」ではなく「**再実行の代わり**」としてだけ案内すること——案内文が「結果を見るだけなら」と書いているのはそのためです。変えたら流す。変えていないなら読み直す。この区別だけは残ります。

## 検証手順: 一瞬で返ることを確かめる

**前提**

- 1 作目 第 1 回のラッパーが、全文を `tmp/test_last.log` に残していること
- その上に、この章の再表示の入口（`--last`）と、案内文への 1 行を足し終えていること

**所要時間**: 5 分

**手順**

1. **AI に**、テストを 1 回、普通に走らせます。ここで `tmp/test_last.log` と実行日時が作られます
2. **あなたが** `--last` を叩きます
3. **あなたが**、適当なファイルを 1 つ触ってから（`touch` でも 1 行足すでも構いません）、もう一度 `--last` を叩きます

**合格条件**（すべて満たすこと）

- 手順 2 で、**何も実行されない**（テストが走り出したら、`--last` が再実行になっています）
- 手順 2 で、前回と**同じ件数の行**が返る
- 手順 2 が、**1 秒以内に**返る
- 手順 3 で、1 行目の**実行日時が、手順 1 のときのまま**である

**合格しなかったとき**

- **手順 2 でテストが走り出した** —— `--last` がログを読まず、実行に回っています
- **手順 3 で日時が出ない** —— ⚠️ ここが本体です。日時が無いと、コードを変えた後の `--last` が「今の結果」に見えます。1 行目に必ず出す形へ直します

**後始末**

- 手順 3 で触ったファイルを、変更していれば戻します

⚠️ 確かめたのは「読み直しが速い」ことだけです。**`--last` は、コードを変えていないときの近道です。** 変えたら流す、変えていないなら読み直す——この区別だけは、仕組みでは消えません。

---

次回は「偽の失敗を読まない技術」。**私は、出てきた失敗を読み分けません。**それでも、本物の失敗を見落としたことはありません。
