第4部 ハーネス · 第11回 / 全20回 · 15分くらい
「確かめたつもり」をなくす。第3世代の限界
第3世代の区切りの回です。テストが通っても、本番で動かないことがあります。確かめた場所と、実際に動く場所がずれているからです。この回では、自分の環境で実際に起きた「確かめたつもり」を4つの形に分けて、それぞれの防ぎ方を決めます。
履修 0 / 20 回
この回を読み終えると、できるようになること
- 確かめた環境と本番の環境がずれる例を、権限・場所・時刻の面から挙げられる
- テストや試し実行が本番を汚す形を説明し、防ぐ作りにできる
- 検査そのものが壊れていないかを、わざと失敗させて確かめられる
専門用語は、初めて出たところで括弧に短い説明を付けています。説明が長くなるものには ※番号を付け、ページの終わりの用語メモにまとめました。
1ずれ1:手で動かす自分と、定時実行の自分は、権限が違う
手で動かして確かめたスクリプトが、定時実行では動かない。自分の環境では、原因の多くが権限でした。
macOS では、書類フォルダや Downloads、クラウドの同期フォルダを読むのに、アプリごとの許可(フルディスクアクセス※1など)が要ります。ターミナルから手で動かすと、ターミナルの許可で読めます。launchd※2 から動かすと、その許可は使えません。読めないとエラーにならずに「0件」として進むことがあり、自分の環境では、画像の振り分けジョブが「0件・成功」を57回続けていました。
だから、新しいジョブや直したジョブは、本番と同じ呼ばれ方で1回動かしてから完了にします。手で動かして通っただけでは、確かめたことになりません。
2ずれ2:テストが本番に触れている
テストのつもりで動かした処理が、本物の記録を書き換えていた、ということも起きました。自分の環境のテストは、本番のロックファイル、本番の鍵のファイル、本番のログに触れていて、212件中14件が失敗したままになっていました。テストが書いた警告は本番のログに混ざり、見張りの仕組みが誤った警報を出していました。
防ぎ方は、本物の置き場所(ロック、ログ、状態のファイル、鍵)を、モジュールの先頭の差し替えられる1か所にまとめ、テストではそこを一時フォルダに差し替えることです。関数の中でパスを組み立てていると、差し替えられません。
3ずれ3:試し実行が、本物を書き換える
「試しに動かすだけ(dry-run※3)」の実行が、成功の記録を書いてしまう、ということもありました。壊れているジョブを調べるために試し実行をしたら、その実行が「成功」を記録して、壊れている証拠を上書きしてしまったのです。
試し実行は、送り先のフォルダも作らない、記録も書かない、が原則です。自分のバックアップのジョブは、試し実行でも送り先のフォルダを作ってしまう作りだったので、直しました。試し実行が本物に何も書かないことを、テストで確かめておくと安心です。
4ずれ4:「読むだけ」のはずのコマンドが書き換える
情報を取り出すだけに見えるコマンドが、実はファイルを書き換える、ということがあります。自分は、macOS の設定ファイルから値を取り出す plutil -extract を調べもののために何十件にもかけて、51件の設定ファイルを壊しました。出力先を指定しないと、取り出した値で原本を上書きするコマンドだったのです。
初めて使うコマンドや、たくさんのファイルにまとめてかけるコマンドは、まずコピーした1件で試し、原本が変わっていないことを確かめてから本物に使います。AIに頼むときも、「コピーで試して、変わっていないことを確かめてから」と書きます。
5検査そのものを確かめる
検査がいつも「合格」を返していたら、検査が壊れている可能性があります。わざと失敗するはずの入力を1つ入れて、ちゃんと落ちるかを確かめます。落ちない検査は、無いのと同じです。
この考え方を広げたものに、ミューテーションテスト※4があります。コードをわざと少し壊して(条件を逆にする、数字を変えるなど)、テストがそれを見つけられるかを調べるやり方です。全部を自動でやらなくても、「大事な検査に、わざと壊した入力を1つ流す」だけで、かなりのことがわかります。
6第3世代の限界
1回の作業なら、ここまでで十分に安全にできます。残るのは、人がその場にいないと始まらないことです。夜中や休みの日にも回したくなったら、次の段(ループ)が必要になります。
そして、ループに進むと、ここで見た4つのずれは、もっと見つけにくくなります。人がその場で結果を見ないからです。だからこの回の確かめ方は、ループを作る前に身につけておきたいものです。
誤解よくある思い違い
手で動かして通ったから、定時実行でも動く
定時実行では、権限・フォルダ・環境変数が手で動かすときと違います。本番と同じ呼ばれ方で1回動かすまでは、確かめたことになりません。
試し実行なら、何をしても安全
試し実行が記録を書いたり、フォルダを作ったりする作りになっていることがあります。何も書かないことを、テストで確かめておきます。
この段が要るとき
- AIの出力を毎回人が全部読んでいて、量に追いつかない
- 破られたら困るルールがある
- 指示や前提を変えたとき、良くなったかを確かめたい
要らないとき(ここで止めてよい)
- 量が少なく、人が全部読んでも間に合う
- 良し悪しが測れない仕事が中心(人の目で十分)
演習手を動かして確かめる
演習1
クラウドの同期フォルダの写真を整理するスクリプトを作りました。ターミナルから動かすと正しく動きます。launchd に登録する前に、何を確かめますか。
答えを見る
①launchd から1回動かして、手で動かしたときと同じ件数を処理するか(0件になっていないか)を確かめます。読めないときに「0件・成功」で終わる作りなら、②読めなかったときは失敗として記録するように直します。写真を動かす処理なので、③最初はコピーしたフォルダで試し、元に戻せる記録(どこからどこへ動かしたか)を残す作りにしておきます。
演習2
「テストが全部通っている」のに、本番で不具合が出ました。テストの側にどんな問題がありそうか、2つ挙げてください。
答えを見る
例:①テストが本番と違う環境(権限、フォルダ、データ)で動いていて、本番の条件を再現していない。②テストの検査が壊れていて、壊れた入力でも合格を返している(わざと壊した入力を流して、落ちるかを確かめていない)。ほかに、テストが本番のファイルに触れていて、結果が本番の状態に左右されている、も考えられます。
データを消す・上書きする・移すような処理を、本物のデータで試すときは、必ず先に控えを取ってください。「試しのつもり」がいちばん危ない場面です。
用語メモ本文の ※番号の説明
- ※1フルディスクアクセス macOS で、アプリが書類フォルダやメール、他のアプリのデータなどを読むための許可。システム設定のプライバシーの項目で、アプリごとに与える。手で動かすときと定時実行のときで、使われる許可が違うことがある。 本文へ戻る ↩
- ※2launchd macOS で、決まった時刻やきっかけでプログラムを動かす仕組み。登録には plist という設定ファイルを使う。Linux の cron と同じような役目をする。 本文へ戻る ↩
- ※3dry-run(試し実行) 実際には何も変えずに、何が起きるかだけを表示する実行のしかた。本来は何も書き込まないはずだが、作りによっては記録を書いてしまうことがある。 本文へ戻る ↩
- ※4ミューテーションテスト プログラムをわざと少し壊したもの(ミュータント)を作り、テストがその壊れを見つけられるかを調べるやり方。見つけられないなら、テストが弱いということになる。 本文へ戻る ↩