2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

テストが本番相当のデータを3回壊した話 — 疑うべきは『他人』より『自分』だった

2
Posted at

この記事は Zenn からの転載です。元記事: https://zenn.dev/berrylove/articles/test-broke-production-data-three-times


先日公開した本『AI 国家運営』の第9章では、テストコードが本番相当のデータを3回壊した事故を扱いました。本では対処(隔離・出口の防御・回帰確認)に重心を置いたので、この記事では逆に、原因にたどり着くまでの調査プロセスだけを切り出します。最初の仮説は外れていて、正しい原因にたどり着けたのは「疑わしきは自分を疑う」という地味な裏取りのおかげでした。

起きたこと: 何度直しても壊れる

個人開発のツール群に、個々のデータを1件ずつ処理した結果を、全量まとめて1つのインデックスファイルへ書き出す関数がありました。本来なら実データ201件分の内容が反映されるはずのファイルが、ある日、テスト用に用意した合成データ1件分だけに置き換わっているのが見つかりました。

ツールを再実行して201件分を復元し、いったんは片付いたように見えました。ところが同じ壊れ方が短期間に3回連続で発生しました。1回目は操作ミスの可能性も考えましたが、同じ壊れ方が3回続いたことで「再現可能な経路がどこかにある」と疑いを強めました。

最初の仮説: 「別のエージェントが競合したのでは」

このリポジトリでは複数のエージェントが並行して作業していました。マルチエージェント運用では、複数の作業主体が同じファイルに触れる場面は実際にあります。そのため最初に立てた仮説は「別のエージェントが同時に書き込んで競合したのではないか」というものでした。

この仮説は、もっともらしく聞こえます。実際に起こりうる話ですし、「自分は悪くない」という結論のほうが調査する側としては楽です。しかし、もっともらしさと正しさは別物です。

仮説を裏取りする — 決め手は「中身の一致」

競合を疑うなら、競合の跡を探すのが筋です。ログやタイムスタンプを見ても、他のエージェントが該当ファイルに触れた形跡は見つかりませんでした。ただ、跡が見つからないことは競合の不在の証明にはなりません。ここで即断せず、もう一段確実な裏取りをしました。

壊れた後のインデックスファイルの中身と、テストコードが使っている合成データの中身を突き合わせたのです。

両者は完全に一致していました。これで「書き込まれた内容の出どころはテストの合成データである」ことが確定しました。そこから、その合成データを使って書き込み関数を呼ぶテストを洗い出し、原因の2件を特定。壊していたのは他のエージェントではなく、そのテストを実行していた自分自身でした。

原因はテストコード側にありました。実データへの書き込みを伴う全量書き出し関数を呼び出すテストが2件あり、どちらも合成データ1件だけを使う設計でした。当時の設計では、書き込み先を決めるグローバル定数を、テスト実行時だけ一時的にテスト用の場所へ差し替える(monkeypatch)必要がありました(恒久策としては、出力先を引数で渡せる設計にするのが本筋です)。この2件のテストは、その差し替えを行わないまま関数を呼んでいました。テストを実行するたびに、正規の出力先パスへ合成データ1件分の内容がそのまま上書きされていた、というのが実態です。

この調査プロセスから持ち帰れること

1. もっともらしい仮説ほど、裏取りを1段厚くする。 「他人(他のエージェント)が悪い」という仮説は、調査する側の心理的にも通りやすく、しかも一見もっともらしい状況証拠(並行作業していた事実)まであります。だからこそ、状況証拠だけで確定させず、もう一段踏み込んだ裏取りが要ります。

2. 裏取りの型は「中身の一致」を見ることです。 ログに跡がないことは「否定の証拠」にはなっても、「別の犯人がいる」ことの証明にはなりません。一方、壊れたデータの中身と疑わしい処理の出力を突き合わせて完全一致すれば、それは強い肯定の証拠になります。「跡がない」で止めず、「一致するか」まで確認する。この一段の違いが、誤診断のまま対処を始めるか、正しい原因に到達するかを分けました。

3. マルチエージェント環境では、この手の誤診断が特に起きやすいと考えたほうがいいです。 複数の作業主体が同じリポジトリに触れる環境では、「他の誰かが壊したのだろう」という仮説が常に候補に挙がります。もっともらしいからといって採用してしまうと、本当の原因(この場合はテストコードの隔離漏れ)を放置したまま、同じ事故が4回目、5回目と繰り返されることになります。実際、今回も1回目・2回目は原因を突き止めないまま復旧だけで終わらせていたため、未隔離のテストが残り続け、同じ事故が繰り返されました。

直した内容は本に書きました

隔離(monkeypatch の徹底。今回の事故への直接の再発防止はこれ)・出口側の防御(読み込み失敗時は中断・書き込みはアトミックに。こちらは別種の破損への備えで、今回の事故は防げません)・回帰確認(152件のテスト合格+テスト実行前後で実データのハッシュが変わらないことの確認)という3段構えの対処は、本の第9章に書きました。この記事で書いた「原因特定までの調査プロセス」と、本に書いた「対処の設計」は補い合う関係にあります。

なお、この事故は複数エージェントでの検収運用にも教訓を残しています。エージェントからの「大丈夫でした」という自己申告をそのまま信じず、実物(ファイルの中身・ハッシュ値)で裏取りする習慣があったからこそ、「壊れた中身とテストデータの一致」という決め手にたどり着けました。この検収運用については本の第4章で扱っています。

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?