今回は、テストの再実行の話です。再実行というのは、コードを 1 文字も変えていないのに、同じテストをもう一度走らせることです。AI はこれをよくやります——「通っていることを確認します」「念のためもう一度」。そのたびに私は、結果が変わらないと分かっているものを、最後まで待っていました。
1 作目「読まない技術」の第 1 回で、テストの実行の入口をラッパー 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 は結果の確認と再実行を区別しない。前回の結果が読める場所があれば、再実行は起きない。
CC BY 4.0
仕組み: 前回の結果を読める場所にする
1 作目 第 1 回のラッパーは、全出力を毎回 tmp/test_last.log に残しています。つまり「確認」に必要なものは、もう手元にあります。足すのは再表示の入口 1 つです。
# 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 で確認しても、時刻の古さが目に入る形にしておきます。
CC BY 4.0 はここまで
待たなくなったもの
確認のためのテスト実行です。4 分半の進捗表示を、私はもう眺めていません。結果は変わらないと分かっているものを待つ時間が、シリーズを通して一番大きい削減です——出力の行数ではなく、実際に待つ時間が減ります。
CC BY 4.0
注意: --last は「変えていない」ときだけの近道
死角ははっきりしています。コードを変えたのに AI が --last で確認すれば、古い結果を新しい結果として読みます。守りは二つで足ります。一つは上に書いた日時の常時表示。もう一つは、--last を「実行の代わり」ではなく「再実行の代わり」としてだけ案内すること——案内文が「結果を見るだけなら」と書いているのはそのためです。変えたら流す。変えていないなら読み直す。この区別だけは残ります。
検証手順: 一瞬で返ることを確かめる
前提
- 1 作目 第 1 回のラッパーが、全文を
tmp/test_last.logに残していること - その上に、この章の再表示の入口(
--last)と、案内文への 1 行を足し終えていること
所要時間: 5 分
手順
- AI に、テストを 1 回、普通に走らせます。ここで
tmp/test_last.logと実行日時が作られます - あなたが
--lastを叩きます - あなたが、適当なファイルを 1 つ触ってから(
touchでも 1 行足すでも構いません)、もう一度--lastを叩きます
合格条件(すべて満たすこと)
- 手順 2 で、何も実行されない(テストが走り出したら、
--lastが再実行になっています) - 手順 2 で、前回と同じ件数の行が返る
- 手順 2 が、1 秒以内に返る
- 手順 3 で、1 行目の実行日時が、手順 1 のときのままである
合格しなかったとき
- 手順 2 でテストが走り出した ——
--lastがログを読まず、実行に回っています - 手順 3 で日時が出ない —— ⚠️ ここが本体です。日時が無いと、コードを変えた後の
--lastが「今の結果」に見えます。1 行目に必ず出す形へ直します
後始末
- 手順 3 で触ったファイルを、変更していれば戻します
⚠️ 確かめたのは「読み直しが速い」ことだけです。--last は、コードを変えていないときの近道です。 変えたら流す、変えていないなら読み直す——この区別だけは、仕組みでは消えません。
CC BY 4.0 はここまで
次回は「偽の失敗を読まない技術」。私は、出てきた失敗を読み分けません。それでも、本物の失敗を見落としたことはありません。