Build は通るのに業務が壊れる、典型 5 パターン
コンパイル成功とユニットテスト緑だけで「完了」にすると、業務シナリオで普通に壊れます。私が実際に踏んだ 5 つのサイレント失敗パターンを並べておきます。
なぜ書いたか
「build OK、unit testオールグリーン、AIも完了と言っている」状態で、画面操作シナリオを通したら 普通に業務が壊れていた という経験を、もう何度も繰り返しています。今回は、私が踏んだサイレント失敗の典型5パターンをまとめておきます。
5パターン
1. 進行ステータス判定漏れ(Progress flag drift)
ステータス管理が複雑な画面で、ボタンの可視 / 活性条件に 使うべきステータスフィールド を見落とすパターン。
- 元実装:
IsDecided && !IsCancelledのような複合条件 - 移行後:
IsDecidedだけ見ている → 取消済み行で削除ボタンが押せる
buildは通るし、ハッピーパスは動きます。特定のステータスの組み合わせ でだけ壊れます。
2. UI / Saveタイミングのずれ(UI-save mismatch)
UIで入力した値が、ボタンクリック時に親モデルに反映されておらず、空値でAPIを呼ぶパターン。
- 元実装(WinForms): フォーカスが外れたら値が確定 → クリック時には入っているはず
- 移行後(Blazor): バインディングのタイミング次第で、クリック直前の値が入っていない
ユニットテストではAPI呼び出しを直接モックするので、UI経由の値が抜ける事故は検出できません。詳細は Tab/blur依存の罠 で書きました。
3. 権限ガップ(Permission gap)
UI側で「高権限ユーザーのみ表示」のボタン表示制御は入れたが、API側のロール検査を忘れているパターン。
- ボタンを隠してもエンドポイントは公開されている
- 一般ユーザーが直APIを叩けば実行できてしまう
buildもテストも通る。直APIを叩く悪意 がない限り、普通の操作では気づきません。詳細は 二重防御の話。
4. 業務同等性の崩れ(Business parity break)
UIは完璧に再現したが、裏で 触っているテーブルや呼んでいる関数が違う パターン。
- 削除ボタンが違うテーブルを消す
- 名称解決のOracle関数を呼び忘れて、コード列が表示される
- イベント連動の自動更新が抜けている
buildもテストも通る。画面操作も「ボタンを押すと何かが反応する」ところまでは正しい。結果の正しさ だけがズレている。詳細は 画面の見た目は同じ、でも裏では違うテーブルを消していた話。
5. ビルド後の周辺リグレッション(Post-build regression)
スライスAの修正が、スライスBの機能を壊すパターン。
- 共通モジュールの関数を変えたら、別画面の挙動が変わる
- DTOのフィールド型を変えたら、別APIのレスポンスが壊れる
スライスAの単体テストは通る。スライスBのテストが薄いと気づけない。
わかったこと
サイレント失敗は 共通の特徴 を持っています。
- buildは通る
- 単体テストは通る
- ハッピーパスでは動く
- 特定の操作シーケンス、または特定のデータ状態でだけ壊れる
なので、「build OK = 完了」の判定基準では絶対に検出できません。検出のためには:
- 再現シナリオベースのレビュー(再現シナリオ駆動)
- 危険信号ベースの観点(画面レビューの危険信号チェック)
- 業務同等性のレビュー(操作優先のレビュー順)
の3つをReviewerの固定観点に置くようにしました。
次にやること / 未解決の問題
- 5パターンそれぞれに自動検出ルールを書きたい(権限ガップはAPIテストで検出可能、UI/SaveタイミングはE2Eで検出可能、など)
- AIに「これら5パターンに該当しないか」を毎スライスでチェックさせるプロンプトを試行中
渡邊 賢
等差級数的Commit 運営 / ICD VIETNAM.LLC General Manager
AI駆動開発と段階的なレガシーモダン化をテーマに、日々の試行錯誤をこのブログに記録しています。
プロフィール詳細 arrow_forward似たような課題に困っている方、一緒に考えませんか。
AI駆動開発・Vibe Coding・レガシーマイグレーションに関するご相談を受け付けています。