クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

回帰テストで再発を防ぐ

このレッスンのあとで: バグの報告を、失敗するテストに変え、バグを直して、テストを残せる。

60分のレッスンコマンド13件毎日使う Linux コマンドのラボ:エンジニアが暗記している30のコマンド

直したバグは戻ってくる

回帰とは、一度直したバグが戻ってくることです。動いていた機能が、変更のあとで動かなくなることも回帰と呼びます。回帰テストは、1つのバグのために書くテストで、そのバグが静かに戻らないようにします。

このレッスンでは、お客様がバグを報告します。先にテストを書き、そのあとで直します。

このレッスンのゴール

メモ

バグの報告を、失敗するテストに変え、バグを直して、テストを残せる。

重要な言葉

ことばいみ
回帰直したバグが戻ること。動いていた機能が壊れること
回帰テスト報告された1つのバグのために書き、ずっと残すテスト
バグ報告利用者が見た間違いと、起こした入力
赤テストが失敗した実行
緑すべてのテストが通った実行
隣のケース報告の入力の隣の入力。修正が、バグを動かしただけではないと確かめる

学生が入力するセルは、このプレビューでは空白です。

バグ報告をテストにする

店は、10000円以上の注文を1割引きにします。お客様が書きました。「ちょうど10000円使ったのに、割引がありませんでした。」

この報告に入力が入っています。10000円です。まずフォルダーと、欠陥のある今のコードを作りましょう。

レッスン用のフォルダーを作る

コマンド
mkdir -p ~/regtest

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

フォルダーに入る

コマンド
cd ~/regtest

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

今の店のコードを書く

コマンド
printf 'def discount(total_yen):\n    if total_yen > 10000:\n        return total_yen // 10\n    return 0\n' > shop.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

直す前にテストを書く

お客様の入力そのままで、報告をテストにします。名前は、お客様が見たことにすると、失敗の表示が報告のように読めます。

直す前に実行します。必ず失敗しなければなりません。壊れたコードで通るテストは、何も証明しません。

報告からテストを書く

コマンド
printf 'import unittest\nfrom shop import discount\n\n\nclass DiscountReport(unittest.TestCase):\n    def test_exactly_10000_yen_gets_a_tenth_off(self):\n        self.assertEqual(discount(10000), 1000)\n' > test_shop.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

実行して、失敗を見る

コマンド
python3 -m unittest test_shop 2>&1 | grep -E "^(OK|FAILED|AssertionError)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

テストが示す所だけを直す

コードは > と書いていますが、決まりは「以上」です。>= に変えて、他は何も変えません。そのあと、テストをもう一度実行します。緑になるはずです。

大なりの記号を変える

コマンド
sed -i 's|total_yen > 10000|total_yen >= 10000|' shop.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

テストをもう一度実行する

コマンド
python3 -m unittest test_shop 2>&1 | grep -E "^(OK|FAILED|AssertionError)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

バグの隣のケースを足す

修正は、バグを消さずに動かしただけ、ということがあります。>= 10000 と書くつもりで、うっかり >= 9999 と書くと、9999円の注文まで割引になります。だから、報告の入力の両側の入力も試します。

例: 境界のまわりのケース

注文(円)受け取る割引そのケースがある理由
999901円足りない。割引はまだない
100001000報告: ちょうど境界
1000110001円上。整数の円で切り捨て
250002500ずっと上。割引に上限はない

学生が入力するセルは、このプレビューでは空白です。

隣のテストを2つ足す

コマンド
printf '    def test_one_yen_under_gets_nothing(self):\n        self.assertEqual(discount(9999), 0)\n\n    def test_over_the_line_gets_a_tenth(self):\n        self.assertEqual(discount(25000), 2500)\n' >> test_shop.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

3つとも実行する

コマンド
python3 -m unittest test_shop 2>&1 | grep -E "^(OK|FAILED|AssertionError)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

テストが修正を守ると確かめる

回帰テストの価値は、バグが戻ったときに出ます。不注意な変更のつもりで、わざとバグを戻し、テストが捕まえるのを見ます。そのあと、修正を戻します。

バグを戻す

コマンド
sed -i 's|total_yen >= 10000|total_yen > 10000|' shop.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

テストを実行する

コマンド
python3 -m unittest test_shop 2>&1 | grep -E "^(OK|FAILED|AssertionError)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

修正を戻す

コマンド
sed -i 's|total_yen > 10000|total_yen >= 10000|' shop.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

もう一度テストを実行する

コマンド
python3 -m unittest test_shop 2>&1 | grep -E "^(OK|FAILED|AssertionError)"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

バグを直してから、通るテストを書いて終わりにする人がいます。そのテストは一度も赤になっていないので、欠陥を捕まえられるかわかりません。先に書き、失敗を見てから、直します。

さらに: 入力のない報告

入力のない報告もあります。「火曜日に合計がおかしかった」のような報告です。テストを書く前に、入力を見つけなければなりません。

再現できる入力を得るために、お客様に聞く質問を3つ挙げましょう。最初に聞くのはどれでしょうか。

このラボとソースについて: 毎日使う Linux コマンドのラボ:エンジニアが暗記している30のコマンド

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。