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

無料レッスン

テストカバレッジの読み方

このレッスンのあとで: カバレッジの数字を読んで、それが見逃すものを説明することができる。

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

テストカバレッジの読み方

テストカバレッジとは、テストを動かしたとき、プログラムのどれだけが実際に実行されたかを表す割合です。一度も動いていない行が、見つかります。

「カバレッジ80%」と言われたら、残りの20%は誰も確かめていません。その20%に、バグが隠れているかもしれません。

このレッスンのゴール

メモ

カバレッジの数字を読んで、それが見逃すものを説明することができる。

キーワード

ことばいみれい
カバレッジテストが動かしたコードの割合80%
行カバレッジ実行された行の数を、全部の行の数で割った割合
分岐カバレッジif の真と偽の、両方を通ったかを数える割合
トレース実行された行を順に残した記録
未実行の行テストの間に、一度も動かなかった行

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

カバレッジはどの行が動いたかの割合

テストを動かしながら、どの行が実行されたかを記録します。実行された行の数を、全部の行の数で割ったものが行カバレッジです。

下の表は、成績を A、B、C に分ける関数を、5つの部分に分けたものです。90点と60点の2つのテストでは、1つの部分が動きません。

例: 2つのテストで動いた部分

印部分の内容90点で動く60点で動く
1最初の if を調べる動く動く
2"A" を返す動く動かない
3次の if を調べる動かない動く
4"B" を返す動かない動く
5"C" を返す動かない動かない

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

動いた印を数えるコード

コード: python
ran = []

def grade(score):
    ran.append(1)
    if score >= 80:
        ran.append(2)
        return "A"
    ran.append(3)
    if score >= 50:
        ran.append(4)
        return "B"
    ran.append(5)
    return "C"

for score in [90, 60]:
    grade(score)

done = []
for mark in ran:
    if mark not in done:
        done.append(mark)
print("動いた印:", done)
print("カバレッジ:", len(done) * 100 // 5, "%")
# リストに 10 を足して、100% になるか確かめましょう。

Python の trace で未実行の行を探す

Python には、実行された行を数える trace モジュールが付いています。--missing を付けると、一度も動かなかった行の頭に >>>>>> が付きます。

ラボでは、成績の関数に 90 と 60 の2つだけを渡して動かします。次に、10 も渡して、印が消えるかを確かめます。

作業用のフォルダを作る

コマンド
mkdir -p ~/testing/coverage

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

そのフォルダへ移る

コマンド
cd ~/testing/coverage

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

2つの点数で動かす版を書く

コマンド
printf 'def grade(score):\n    if score >= 80:\n        return "A"\n    if score >= 50:\n        return "B"\n    return "C"\n\n\nprint(grade(90))\nprint(grade(60))\n' > grade.py

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

trace を付けて動かす

コマンド
python3 -m trace --count --missing --coverdir=. grade.py

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

まず A と B が表示される

プログラム自身の出力として、A と B が表示されます。同時に、grade.cover というファイルが作られます。

次のコマンドは、その中から >>>>>> の付いた行だけを出します。

未実行の行を探す

コマンド
grep '>>>>>>' grade.cover

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

出るのは return "C" の1行

出力は、行頭が >>>>>> で、そのあとに return "C" が続く1行です。90点でも60点でもこの行には届かず、一度も動いていません。

今度は、10点も試す版を書いて、同じ調べ方をします。

3つの点数で動かす版を書く

コマンド
printf 'def grade(score):\n    if score >= 80:\n        return "A"\n    if score >= 50:\n        return "B"\n    return "C"\n\n\nprint(grade(90))\nprint(grade(60))\nprint(grade(10))\n' > grade_all.py

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

もう一度 trace で動かす

コマンド
python3 -m trace --count --missing --coverdir=. grade_all.py

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

未実行の行の数を数える

コマンド
grep -c '>>>>>>' grade_all.cover

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

数えると 0 になる

A、B、C が表示されたあと、最後のコマンドは 0 と表示します。未実行の行が0本で、行カバレッジが100%になったからです。

行が全部動いても分岐は残る

if には、条件が真の道と偽の道があります。分岐カバレッジは、その両方を通ったかを数えます。

会員なら100円引く関数を、会員の場合だけ試すと、すべての行が動きます。行カバレッジは100%です。しかし、会員でない道は一度も試されていません。

例: 行と分岐のカバレッジ

テスト動いた行行カバレッジ通った分岐
会員だけ4行すべて100%2つのうち1つ
会員と非会員4行すべて100%2つのうち2つ

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

会員だけを試したコード

コード: python
def discount(price, member):
    if member:
        price = price - 100
    return price

# 会員の場合だけ試しました。すべての行が動きます。
print(discount(1000, True))
# 次の行の # を外して、会員でない場合も試しましょう。
# print(discount(1000, False))

100% でも正しいとは言えない

カバレッジは、コードが動いたことしか言いません。結果が正しいかは、確認の行(アサーション)が決めます。

何も確かめないテストでも、関数を動かせばカバレッジは上がります。数字は目標ではなく、見落としを探す地図として使いましょう。

動かしても確かめないテスト

コード: python
def total(price, count):
    return price + count

# このテストは関数を動かしますが、何も確かめません。
total(120, 3)
print("エラーなしで終わりました")
# 次の行の # を外すと、確かめる1行が働いて、止まります。
# assert total(120, 3) == 360

よくある間違い

注意

「カバレッジが100%なら、バグはない」と考える人が多くいます。100%は、すべての行が動いたことを言うだけです。結果を確かめていなければ、間違った答えのまま通ります。

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

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