本文へ移動
AI Dev Lab Japan AI開発ツール、AIコーディングエージェント、M...

Codexでテストが薄いコードを触る前に決めること

Codexでテストが薄いコードを触る前に決めることの要点をタイトルと確認軸で示すアイキャッチ

3行まとめ

Visual変更前の4点現状を先に固定します。
Observe

観測。

Fixture

入力。

Golden

出力。

Compare

比較。

テストが薄いコードは、直す前に今の挙動を証拠として残します。

  • テストが薄いコードをCodexに直させる前に、まず現状の入力、出力、画面、手動確認を証拠として残します。
  • characterization test、golden output、snapshot、manual checklistは役割が違います。全部をunit testへ寄せなくて大丈夫です。
  • 修正後は「テストが通った」だけでなく、「守るべき既存挙動が残ったか」「変わった出力に承認があるか」を見ます。

古いコードをCodexに直してもらうと、作業は速くなります。読みにくい条件分岐を整理する。型を付ける。エラー処理を足す。古いAPI呼び出しを置き換える。人間が後回しにしていた仕事を進めやすくなります。

ただし、既存テストが薄いコードでは、速さがそのままリスクになります。Codexが「自然にきれいな実装」へ寄せた結果、実は利用者が頼っていた微妙な挙動を変えることがあります。仕様書に書かれていないが運用で使われている出力、古い画面の並び順、空値の扱い、例外時のログ、CSVの列順。こうしたものは、テストがなければ壊れても気づきにくいです。

この記事では、テストが薄い既存コードをCodexに触らせる前に、現状の挙動をどう固定するかを扱います。コード移行全体のcheckpointやrollbackは、公開済み記事のCodexでコード移行を進める前に決めることで扱いました。ここでは、その前段である「直す前に観測する」作業へ絞ります。

この記事でわかること

Visual先に決めるもの変更前の準備です。
Scope

範囲。

Evidence

証拠。

Forbidden

禁止。

Review

確認。

AIに直させる前に、変えてよいものと守るものを分けます。

  • characterization testをAI変更前に使う考え方
  • snapshot、golden output、fixture、manual checklistの分け方
  • read-only調査で入口と出口を見つける手順
  • Codexへ渡す変更前パケットの型
  • テストがない範囲を不明として残す方法
  • 修正後にbefore/afterを比較する観点
  • snapshot更新を人間承認へ戻す理由
  • CIに入れる最小確認セット

この記事は、テストを書くべきかどうかの一般論ではありません。テストが十分ではない現実のコードを、どう安全に触り始めるかの話です。

前提知識

Visualテストの種類役割を分けます。
項目内容見方
Character現状。
Snapshot構造。
Golden出力。
Manual手順。

正しさを証明できない時も、少なくとも変化は検出できます。

JestのSnapshot Testingは、出力された構造を保存し、次回実行時に差分を見る仕組みです。Playwright Testにもvisual comparisonやsnapshot系の確認があり、画面やaccessibility寄りの変化を検出できます。GitHub Actionsは、build、test、deployなどをworkflowとして実行できます。

これらは、Codex専用の仕組みではありません。ただ、Codexに修正を任せる前には相性がよいです。AIが大きく書き換える前に、今の挙動を観測できる形にしておくと、変更後のレビューが楽になります。

characterization testとは

characterization testは、理想仕様を証明するテストというより、今の挙動を記録するテストです。

古いコードでは、仕様書が古い、担当者がいない、誰も全体を覚えていない、ということがあります。その時に「正しい仕様」を最初から決めようとすると止まります。まずは、代表的な入力に対して今何が返るかを固定します。

snapshotとgolden outputの違い

snapshotは、UI構造やobject構造など、出力の形を保存して差分を見る時に向いています。

golden outputは、期待される出力fileや文字列を保存して比較する考え方です。CSV、JSON、Markdown、メール本文、API response、変換結果などに向いています。

どちらも万能ではありません。snapshotを丸ごと更新すると、壊れた変化も通ってしまいます。golden outputも、何を代表例にするかを間違えると守りたい挙動を守れません。

まず変更を止めて観測する

Visualobserve first読む順番です。
  1. 1Read

    読む。

  2. 2Map

    入口。

  3. 3Run

    実行。

  4. 4Record

    記録。

最初の仕事は修正ではなく、今の挙動を見える形にすることです。

テストが薄いコードでは、最初のCodex依頼を「修正してください」にしないほうが安全です。

最初は、read-onlyで観測します。どのfileが入口か。どの関数が出力を作るか。どのcommandで今の挙動を確認できるか。どこにfixtureを置けるか。先に地図を作ります。

read-onlyから始める

Codexには、最初に変更を禁止して調査させます。

例として、「まだfileを編集せず、対象機能の入口、出力、既存テスト、手動確認方法を一覧にしてください」と依頼します。

この段階では、改善案よりも根拠が大事です。対象file、呼び出し元、入力例、出力例、既存test、未確認領域を出させます。

入口と出口を決める

古いコードでは、入口と出口が分からないまま修正に入ると危険です。

入口は、API route、CLI command、UI event、batch job、library functionなどです。出口は、画面表示、DB更新、file出力、log、外部API request、return valueなどです。

Codexには、入口と出口を表にさせます。これだけで、どこを固定すべきかが見えます。

仕様と現状を分ける

仕様と現状は分けます。

仕様上はこうあるべき、現在はこう動いている。この2つを混ぜると、Codexが「正しそうな仕様」に合わせて既存挙動を変えることがあります。

まずは現状を記録し、変えるべき挙動は別に承認します。

証拠を4種類に分ける

Visualevidence set比較材料です。
項目内容見方
Unit関数。
Integration連携。
Golden出力。
Manual人手。

全部をunit testにしようとせず、観測できる証拠を組み合わせます。

変更前の証拠は、unit testだけでは足りません。

古いコードほど、関数単位に切り出されていないことがあります。そこで、証拠をunit、integration、golden output、manual checklistに分けます。

unit

unit testは、関数や小さなmoduleの挙動を固定します。

入力が作りやすく、副作用が少ない場所に向いています。空文字、null、0件、重複、境界値、locale、timezoneなど、壊れやすい入力を選びます。

integration

integration testは、複数moduleを通した挙動を見ます。

API route、DBを使う処理、外部serviceのmock、CLI、batch jobなどです。全部を再現しようとすると重くなるため、代表flowに絞ります。

golden output

golden outputは、変換結果や生成物を保存して比較します。

たとえば、CSV importの結果、Markdown生成、invoice文面、API response、設定file変換、report出力です。人間が読めるfileとして保存すると、reviewしやすくなります。

manual checklist

manual checklistは、自動化できない確認を残す場所です。

古い画面、外部連携、本番に近い権限、社内admin操作などは、自動化が難しい場合があります。その時は、手動確認を「未検証」ではなく、明確な証拠として扱います。

手動確認を弱い証拠にしない

手動確認でも、手順、入力、期待結果、確認者、日時を残せば、レビュー材料になります。

「見た感じOK」ではなく、「この入力でこの画面が表示され、この出力fileが生成された」と書きます。

Codexへ渡す変更前パケット

Visualchange packet依頼の型です。
項目内容見方
Goal目的。
Current現状。
Allowed許可。
Forbidden禁止。

変更前パケットがあると、AIの善意の作り替えを抑えられます。

観測が終わったら、Codexへ変更前パケットを渡します。

これは長い仕様書ではありません。AIが変更中に守るべき境界を短くまとめたものです。

goal

goalには、今回の目的を書きます。

例: 「CSV importのnull処理を修正する」「古いAPI clientを新しいadapterへ置き換える」「画面の並び替え処理を読みやすくする」。

目的が曖昧だと、Codexは周辺の改善まで始めやすくなります。

current behavior

current behaviorには、今の挙動を書きます。

入力、出力、既存test、golden output、manual checklistを短く並べます。ここで「正しいか不明だが現状こう動く」と明記してもかまいません。

allowed change

allowed changeには、変えてよいものを書きます。

例: 「内部実装は変えてよい」「error messageのtypoは直してよい」「処理時間改善のためにloopを置き換えてよい」。

forbidden change

forbidden changeには、変えてはいけないものを書きます。

例: 「CSV列順を変えない」「既存API response fieldを消さない」「snapshotを承認なしに更新しない」「testをskipしない」。

テストがない範囲の扱い

Visualunknown handling不明を分けます。
Unknown

不明。

Fixture

入力。

UI

画面。

Log

記録。

未テスト範囲は、空白ではなくリスクとして扱います。

テストがない範囲を、なかったことにしないのが大事です。

Codexに任せると、未テスト範囲も自然に触れてしまうことがあります。だから、どこが未テストかを先に明示します。

不明を不明として残す

不明なものは、不明として残します。

「このbranchは古い顧客だけが使う可能性がある」「このflagの実運用が分からない」「このerror pathは再現できていない」。こうした情報は、修正前パケットに入れます。

不明を隠すと、Codexが普通のコードとして整理してしまいます。

先にfixtureを作る

fixtureは、入力例です。

CSV、JSON、HTML、log、API response、DB seed、画像、設定fileなど、対象機能が読む入力を残します。fixtureがあると、Codexの修正後に同じ入力で比較できます。

fixtureは完璧でなくてよいです。まず代表例を数個作り、バグ報告や運用例から増やします。

画面は操作と見た目を分ける

UIでは、操作と見た目を分けます。

操作はPlaywrightのlocatorやaccessibility寄りの確認で固定できます。見た目はscreenshotやvisual comparisonで確認します。どちらも必要ですが、混ぜると失敗理由が分かりにくくなります。

修正後の比較を決める

Visualcompare after change差分の見方です。
  1. 1Before

    変更前。

  2. 2Patch

    修正。

  3. 3After

    変更後。

  4. 4Review

    確認。

修正後は、test passだけでなく、守るべき出力が残っているかを見ます。

修正後に何を見るかを、修正前に決めます。

「通ったtestを見る」だけでは足りません。守るべき現状が残っているか、意図して変えた出力がreviewされているかを見ます。

before and after

before/afterは、同じ入力で比較します。

変更前の出力、変更後の出力、変わった理由、承認者を残します。差分がないことを期待する箇所と、差分が出るべき箇所を分けます。

snapshot update

snapshot更新は、必ずreview対象にします。

snapshotが落ちた時に、すぐ更新すると危険です。落ちた理由が、意図したUI変更なのか、壊れた構造なのかを見ます。

reviewer note

reviewer noteには、今回守った挙動、変えた挙動、未確認領域を書きます。

AIが作ったPRでは、diffだけでは意図が見えにくいことがあります。reviewer noteがあると、人間が差分を追いやすくなります。

snapshot更新の承認

snapshot更新は、軽い変更に見えても承認対象にします。

特にUI、API response、CSV、メール本文、契約書、請求書、通知文面のsnapshotは、利用者影響があります。Codexに「snapshot更新は人間承認なしに行わない」と渡します。

CIに入れる最小セット

Visualminimal CI毎回走らせます。
項目内容見方
Fast軽い。
Risky重い。
Manual人手。
Artifact証跡。

CIには、軽い自動確認と人が見る証跡を分けて入れます。

最初から大きなtest suiteを作る必要はありません。

まずは、毎回走る軽い確認、必要時に走る重い確認、人が見るmanual evidenceを分けます。

fast check

fast checkは、PRごとに走る確認です。

unit test、対象moduleのtest、typecheck、lint、golden output比較などです。数分で終わるものを入れます。

risky check

risky checkは、影響が大きい時に走る確認です。

E2E、DBを使うintegration、visual comparison、外部serviceのmock、migration rehearsalなどです。毎回重すぎるなら、labelやmanual triggerで分けます。

manual evidence

manual evidenceは、CIで自動化できない証拠です。

screenshot、操作手順、出力file、確認URL、ログ抜粋、QAメモなどをPRへ添えます。GitHub Actionsのartifactやjob summaryへ残すのも有効です。

よくある失敗

Visualbad patterns変えすぎを避けます。
Rewrite

作り替え。

Blind snap

丸更新。

No fixture

入力なし。

No note

理由なし。

テストが薄い時ほど、きれいな大改修より小さな比較を優先します。

よくある失敗は、テストが薄いからといって、いきなり大きく作り替えることです。

1つ目は、Codexに「きれいにして」と頼むことです。きれいさは人によって違います。目的、守る出力、禁止変更を渡します。

2つ目は、snapshotを丸ごと更新することです。snapshot更新は差分を消す操作でもあります。なぜ変わったかをreviewします。

3つ目は、fixtureなしで修正することです。同じ入力で比較できなければ、直ったかどうかが分かりません。

4つ目は、未テスト範囲をPR本文に残さないことです。分からない範囲を残せば、reviewerが判断できます。

FAQ

Visualよくある迷い判断の入口です。
項目内容見方
何から?入口。
何件?代表。
更新?承認。
捨てる?理由。

迷ったら、変更前後で説明できる証拠があるかへ戻ります。

テストが全くない場合は何から始めますか

入口と出口を1つ選びます。

まず代表入力を作り、今の出力を保存します。unit testが難しければ、CLI実行、API response、生成file、手動確認でもかまいません。

characterization testは正しくない挙動も固定しませんか

固定します。だから、名前やコメントで「現状の記録」と分かるようにします。

バグとして直す挙動は、別のtestで期待値を変えます。現状固定と仕様修正を同じtestに混ぜないほうがreviewしやすいです。

snapshotは使わないほうがいいですか

使えます。ただし、更新を軽く扱わないことが大事です。

snapshotは広く変化を拾える一方で、差分の意味を人間が見ないと危険です。特にCodexが修正したPRでは、snapshot更新理由をPR本文へ残します。

Codexにテスト追加まで任せてよいですか

任せてよいです。ただし、先に「現状を固定するtest」と「仕様変更を確認するtest」を分けます。

AIが書いたtestが実装に寄りすぎていないか、fixtureが代表例として妥当か、未確認領域が残っているかを人間が見ます。

参照した主な情報源

次に読むなら

更新履歴

Visual更新メモ公開時点の整理です。
  1. 2026.05.31

    初版。

テストツールの詳細は、導入時に公式docsで見直します。

  • 2026.05.31 初版公開。