全部が緑のテスト
コーディングアシスタントは、関数のテストを1分で書けます。全部が通ると、安心できます。
でも、失敗できないテストは、何も守っていません。このレッスンでは、テストを頼み、1つずつ「本当に失敗できるか」を確かめます。
このレッスンのゴール
メモ
アシスタントにテストを頼み、そのテストが本当に失敗できるかを判断できる。
キーワード
| ことば | いみ | れい |
|---|---|---|
| 仕様 | コードがすることを、コードより先に書いたもの | |
| 境目 | 規則が変わる値の、すぐ両側 | 12歳と13歳 |
| 役に立たないテスト | コードが間違っていても通るテスト | |
| 写し | 期待値をコードから持ってきたテスト | |
| わざと壊した写し | 小さな間違いを入れた、コードの複製 |
学生が入力するセルは、このプレビューでは空白です。
テストは規則から始める
アシスタントには、コードだけでなく、規則を文章で渡します。例えば「12歳以下は半額。円未満は切り捨て」です。
規則の部分ごと、そして境目ごとに、1つずつ頼みます。境目は規則が変わるところで、ここでは12歳と13歳です。期待値は規則から出します。コードから出すと、テストはコードに同意するだけです。
例: 規則から場合へ
| 場合 | 年齢と運賃 | 期待値 (円) | 確かめること |
|---|---|---|---|
| 子ども | 6歳、230円 | 115 | 半額になること |
| 半額の最後 | 12歳、230円 | 115 | 12歳も半額であること |
| 全額の最初 | 13歳、230円 | 230 | 13歳は全額であること |
| 奇数の運賃 | 5歳、175円 | 87 | 円未満を切り捨てること |
学生が入力するセルは、このプレビューでは空白です。
ありうる頼み方
こんな頼み方があります。「規則は、12歳以下は半額、円未満は切り捨てです。fare(age, yen) のテストを、上の表の1行に1つ書いてください。期待値は、手で書いた数にしてください」
アシスタントが返すものは、毎回違います。返ってきたテストを1つずつ読み、まず境目の12歳と13歳があるかを見ます。
テストは失敗できなければならない
テストが役に立つかを知るには、コードをわざと壊します。小さな間違いを入れた写しを作り、同じテストを動かします。それでも全部通るなら、そのテストは何も守っていません。
次の Run は、フォルダー demo-tests/ に、正しいコード、壊した写し、手で書いた2つの検査を書きます。アシスタントの答えではありません。
正しいコードを書く
docker exec -w /home/node/project agent sh -c "mkdir -p demo-tests && printf '%s\n' '// バスの運賃。12歳以下は半額で、円未満は切り捨てる。' 'function fare(age, yen) {' ' if (age <= 12) return Math.floor(yen / 2);' ' return yen;' '}' 'module.exports = { fare };' > demo-tests/fare.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
壊した写しを書く
docker exec -w /home/node/project agent sh -c "mkdir -p demo-tests && printf '%s\n' '// わざと壊した写し。12歳が半額にならない。' 'function fare(age, yen) {' ' if (age < 12) return Math.floor(yen / 2);' ' return yen;' '}' 'module.exports = { fare };' > demo-tests/fare-broken.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
良い検査を書く
docker exec -w /home/node/project agent sh -c "mkdir -p demo-tests && printf '%s\n' 'const fare = require(process.argv[2]).fare;' 'let failures = 0;' 'function check(name, ok) {' ' if (ok === false) {' ' failures = failures + 1;' ' console.log(\"失敗: \" + name);' ' }' '}' '// 規則から、手で書いた期待値。' 'check(\"6歳\", fare(6, 230) === 115);' 'check(\"12歳\", fare(12, 230) === 115);' 'check(\"13歳\", fare(13, 230) === 230);' 'check(\"奇数の運賃\", fare(5, 175) === 87);' 'console.log(\"good.js、\" + process.argv[2] + \": 失敗 \" + failures + \" 件\");' > demo-tests/good.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
弱い検査を書く
docker exec -w /home/node/project agent sh -c "mkdir -p demo-tests && printf '%s\n' 'const fare = require(process.argv[2]).fare;' 'let failures = 0;' 'function check(name, ok) {' ' if (ok === false) {' ' failures = failures + 1;' ' console.log(\"失敗: \" + name);' ' }' '}' '// 目の前のコードから写した計算。境目も同じ。' 'function expected(age, yen) {' ' if (age < 12) return Math.floor(yen / 2);' ' return yen;' '}' 'fare(12, 230);' 'check(\"呼ぶだけ\", true);' 'check(\"数である\", typeof fare(12, 230) === \"number\");' 'check(\"同じ計算\", fare(12, 230) === expected(12, 230));' 'console.log(\"weak.js、\" + process.argv[2] + \": 失敗 \" + failures + \" 件\");' > demo-tests/weak.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
各検査を各コードに動かす
docker exec -w /home/node/project/demo-tests agent sh -c "node good.js ./fare.js; node good.js ./fare-broken.js; node weak.js ./fare.js; node weak.js ./fare-broken.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
テストはコードを写せる
弱い検査の3つ目は、期待値を、コードの写しで計算します。境目も同じです。壊した写しを見て書かれたので、その間違いまで写しています。壊した写しでは通り、正しいコードでは失敗します。
これが写しです。アシスタントがコードだけを見て、規則を渡されないときに起きます。期待値は、手で書いた数にします。
よくある間違い
注意
テストは多いほど安全だと思う人が多いです。失敗できないテストが15個あっても、守れるものはゼロです。数ではなく、見つけられる間違いを数えます。コードをわざと壊して、どのテストが赤くなるかを見ます。
例: 4回の実行
| 検査 | コード | 表示 |
|---|---|---|
| good.js | fare.js | good.js、./fare.js: 失敗 0 件 |
| good.js | fare-broken.js | 失敗: 12歳、そして 失敗 1 件 |
| weak.js | fare.js | 失敗: 同じ計算、そして 失敗 1 件 |
| weak.js | fare-broken.js | weak.js、./fare-broken.js: 失敗 0 件 |
学生が入力するセルは、このプレビューでは空白です。
さらに: 別の変更で試す
今は、この考えを別の変更で試すのに、よい時です。ラボのバグには触れません。それは別のレッスンの仕事です。代わりに、shop.js の写しに、新しい割引の規則を足します。
規則を文章で書き、アシスタントにテストを頼み、そのコードをわざと壊します。緑のままのテストを書き出し、なぜ何も見つけないのかを言います。