直したのに、まだ間違う
テストが1つ失敗しています。アシスタントに「直して」と頼むと、その1件だけを通す変更が返ることがあります。
別の入力は、間違ったままです。バグを見つけてもらうために、何を渡すか。返ってきた直しを、どう確かめるか。このレッスンで学びます。
このレッスンのゴール
メモ
バグを見つけてもらうために必要なものを渡し、返ってきた直しが原因に効くかを確かめられる。
キーワード
| ことば | いみ |
|---|---|
| 再現 | バグを、何度でも起こせる手順にすること |
| 失敗するテスト | バグがある間は赤で、直ると緑になるテスト |
| 原因 | 間違った結果を出している、コードの場所 |
| その場しのぎ | 報告された1件だけを通す、原因に触れない直し |
| 1つずつ変える | 1回に1か所だけ変え、そのたびに確かめること |
学生が入力するセルは、このプレビューでは空白です。
アシスタントに渡すもの
バグを頼むときは、4つを渡します。失敗する呼び出し、期待した結果、実際の結果、すでに試したことです。「動きません」だけでは、アシスタントは推測するしかありません。
渡すのは、自分が見たことだけです。原因の推測は後にして、事実を先に書きます。これで、再現できる報告になります。
例: バグの報告の4つ
| 渡すもの | 例 | 役目 |
|---|---|---|
| 失敗する呼び出し | boxes(10, 4) | 誰でも再現できる |
| 期待した結果 | 3箱 | 正しい答えを示す |
| 実際の結果 | 2箱 | 間違いの形を示す |
| 試したこと | boxes(12, 4) は3箱で合う | 探す範囲を狭める |
学生が入力するセルは、このプレビューでは空白です。
ありうる頼み方
こんな頼み方があります。「boxes(10, 4) が 2 を返します。期待は 3 です。boxes(12, 4) は 3 で合っています。原因の候補を、理由をつけて挙げてください。まだコードは変えないでください」
アシスタントの返事は、毎回違います。候補の理由が、渡した事実と合っているかを、まず確かめます。
直しは、原因に効かなければならない
直しが返ったら、報告した1件が通るかを見ます。次に、ほかの入力でも動かします。1件だけ通る直しは、その場しのぎかもしれません。
次の Run は、フォルダー demo-debug/ に、壊れた版、その場しのぎの版、正しい版と、確かめるスクリプトを書きます。アシスタントの答えではありません。
壊れた版を書く
docker exec -w /home/node/project agent sh -c "mkdir -p demo-debug && printf '%s\n' '// お弁当を箱に詰める。1箱に perBox 個。必要な箱の数を返す。' 'function boxes(count, perBox) {' ' return Math.floor(count / perBox);' '}' 'module.exports = { boxes };' > demo-debug/boxes-buggy.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
その場しのぎの版を書く
docker exec -w /home/node/project agent sh -c "mkdir -p demo-debug && printf '%s\n' '// その場しのぎの直し。報告された1件だけを通す。' 'function boxes(count, perBox) {' ' if (count === 10 && perBox === 4) return 3;' ' return Math.floor(count / perBox);' '}' 'module.exports = { boxes };' > demo-debug/boxes-patch.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
正しい版を書く
docker exec -w /home/node/project agent sh -c "mkdir -p demo-debug && printf '%s\n' '// 直した版。余りがあれば、もう1箱要る。' 'function boxes(count, perBox) {' ' return Math.ceil(count / perBox);' '}' 'module.exports = { boxes };' > demo-debug/boxes-right.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
確かめるスクリプトを書く
docker exec -w /home/node/project agent sh -c "mkdir -p demo-debug && printf '%s\n' 'const boxes = require(\"./boxes-\" + process.argv[2] + \".js\").boxes;' 'const all = [[10, 4, 3], [12, 4, 3], [11, 4, 3], [0, 4, 0], [1, 4, 1], [8, 4, 2]];' 'const cases = process.argv[3] === \"all\" ? all : all.slice(0, 1);' 'let ok = 0;' 'for (const c of cases) {' ' const got = boxes(c[0], c[1]);' ' if (got === c[2]) ok = ok + 1;' ' else console.log(\"boxes(\" + c[0] + \", \" + c[1] + \"): 期待 \" + c[2] + \"、結果 \" + got);' '}' 'console.log(process.argv[2] + \": \" + cases.length + \" 件中 \" + ok + \" 件が合う\");' > demo-debug/check.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
壊れた版を、報告で確かめる
docker exec -w /home/node/project/demo-debug agent node check.js buggyここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
3つの確かめ方を動かす
docker exec -w /home/node/project/demo-debug agent sh -c "node check.js patch; node check.js patch all; node check.js right all"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
原因を説明する直しを選ぶ
壊れた版は、割り算を切り捨てていました。余りがあれば、もう1箱要ります。正しい版は、切り上げます。原因の説明と、直しが合っています。
その場しのぎは、10個と4個の1件だけを特別扱いします。11個で、また間違います。よい直しは、失敗した理由を説明できます。
よくある間違い
注意
失敗したテストが通れば、直ったと思う人が多いです。そのテストだけを通す変更も、緑にできます。直ったと言えるのは、ほかの入力も通り、原因の説明がつくときだけです。
例: 3つの確かめ方
| 版 | 確かめ方 | 表示 |
|---|---|---|
| buggy | 報告の1件 | boxes(10, 4): 期待 3、結果 2、そして 1 件中 0 件 |
| patch | 報告の1件 | patch: 1 件中 1 件が合う |
| patch | 全部の6件 | boxes(11, 4) と boxes(1, 4) が失敗、6 件中 4 件 |
| right | 全部の6件 | right: 6 件中 6 件が合う |
学生が入力するセルは、このプレビューでは空白です。
さらに: 別のバグで試す
今は、この考えを別のバグで試すのに、よい時です。ラボのバグには触れません。代わりに、shop.js の写しに、小さな間違いを自分で入れます。
失敗する呼び出し、期待、実際の結果を書いて、アシスタントに頼みます。直しが返ったら、報告の1件のほかに、2つの入力で確かめます。