テストが1つも無いコードに、どこからテストを足すか
全部にテストを書くのは無理です。移行で触る所だけに絞ったら、現実的な分量になりました。

この記事の結論
- 全体にテストを書こうとすると、着手できない
- 触る所だけに絞る。触らない所は書かない
- テストは「仕様の確認」ではなく「変わっていないことの確認」
- 全体にテストを書こうとすると、着手できない
- 触る所だけに絞る。触らない所は書かない
- テストは「仕様の確認」ではなく「変わっていないことの確認」
古いコードにはテストが無い。移行で壊していないか確かめたいが、全部に書くのは現実的でない。
目的を取り違えない
ここで書くテストは、正しいかどうかを確かめるものではない。
移行の前後で同じ入力から同じ出力が出るかを見るためのものだ。元の動きが仕様的に間違っていても、それは別の話として扱う。
この違いを決めておかないと、「そもそもこの計算おかしくないですか」という話が混ざって進まなくなる。
書く範囲を絞る
移行で触るファイルだけに絞った。触らないファイルには書かない。
全体の2割くらいのファイルが対象になった。残り8割は、移行後も1行も変わらないので壊れようがない。
入出力を先に記録する
テストを書く前に、いまの動きを記録した。
// 移行前のコードに一時的に仕込む
file_put_contents('/tmp/trace.log',
json_encode(['in' => $_GET, 'out' => $result]) . "n", FILE_APPEND);本番で数日流すと、実際に来ている入力の形が分かる。想像で書いたテストより、ここで取れた値のほうが役に立った。
個人情報が混ざる場合は、そのまま保存しない。項目を絞るか、形だけ記録する。
記録からテストを起こす
取れたログをAIに渡して、テストの形にしてもらう。ここは素直に速かった。
public function test_calc_tax_returns_same_as_before(): void
{
$this->assertSame(10500, calc_tax(10000, 0.05));
$this->assertSame(1050, calc_tax(1000, 0.05));
}値はログから持ってきたものなので、実際に起きた入出力になる。
そのまま使える形
全部に足そうとすると始まらない。壊れたら困る順に3つだけ足す。
- 金額の計算 — 間違えると後から取り返せない
- 権限の判定 — 間違えると見えてはいけないものが見える
- これから触る箇所 — 触る直前に、いまの挙動を固定する
3番目の考え方が実務では効く。テストは品質を上げるためではなく、変える前の状態を記録するために書く。記録があれば、変えた後に「同じか」を機械が答える。
書けないほど絡まっている関数は、それ自体が「先に分けるべき箇所」の印になる。
AIが書くテストの癖
頼み方を変えずに任せると、いま通ることを確認するだけのテストになりがちだった。
実装を読んで、それに合わせたテストを書くので、当然通る。バグがあればバグごと固定される。
対策は、実装を見せずに入出力のログだけを渡すこと。「この入力でこの出力だった。これを保つテストを書いて」と頼むと、実装に引きずられない。
境界は人が足す
ログに出てくるのは実際に来た値だけで、境界の値は入っていないことが多い。
- 0件のとき
- 空文字が来たとき
- 想定より桁が多いとき
ここはどう動くのが正しいかを決める作業なので、人が決める。決めた結果をテストにするのはAIでよい。
カバレッジは目標にしない
率を目標にすると、簡単な所ばかりテストが増える。
見るのは「移行で触るファイルのうち、テストがある割合」にした。触らないファイルは分母に入れない。こちらのほうが、安心して移行できるかどうかに直結した。
テストが書けないコードは、書かずに記録する
DB接続やセッションに絡んで切り出せないコードは、無理にテストにしなかった。
代わりに、移行前後で同じ画面を開いてHTMLを保存し、差分を取る。粗いが、何も無いよりずっとよい。差分が出た所だけ目で見る。
どこまで書くかの線引き
最終的にこうした。
| 対象 | やること |
|---|---|
| 計算・変換など、入出力がはっきりした関数 | テストを書く |
| DBやセッションに絡む処理 | 画面のHTML差分で確認 |
| 移行で触らないファイル | 何もしない |
あわせて読む
- 大きく作り替えるより、少しずつ変えるほうが速かった — 一度に作り直して失敗しました。段階を踏む形に変えた話です。
- コメントに何を書くかで、後から読むときの楽さが変わる — 処理の内容を書いても役に立ちませんでした。書くべきことを整理します。
- サイトアイコンを作り直したとき、意外と手間がかかった話 — 画像を用意するだけでは終わりませんでした。必要な作業を整理します。
まとめ
レガシーコードのテストは、全部に書こうとした時点で頓挫する。触る所だけ、しかも「変わっていないこと」の確認に限る。
実際に来た入出力を記録してから書くと、量も現実的になり、AIに任せられる部分もはっきりした。
新しい記事が出たら、ブラウザの通知でお知らせします。
メールアドレスの登録は要りません。いつでも止められます。
関連記事
RELATED
HTTPの仕組みを図にした。前の話を覚えていない、という前提
HTTPは1往復で完結し、前のやり取りを覚えていません。ログイン状態が保てる理由と、ステータスコードの読み方を図で整理し…
Laravelへ移すとき、どこから手を付けるか決めた
全部を一度に移すと戻れなくなります。順番を決めたら、途中で止めても使える状態を保てました。
動くけれど危ないコードを、先に直す順番にした
エラーで止まるコードより、止まらずに動いてしまうSQLの連結のほうが優先度は上でした。