Python

例外処理とテスト

失敗の原因を読み、想定内の失敗へ対応し、正しい結果を自動で確認しましょう。

01

Tracebackを下から読む

エラーが起きると、Pythonは呼び出し経路と例外名を表示します。まず一番下の「例外名と説明」を読み、その上にある自分のファイル名と行番号を確認します。

エラーになる例PYTHON
prices = [100, 200]
print(prices[2])
表示例OUTPUT
Traceback (most recent call last):
  File "sample.py", line 2, in <module>
    print(prices[2])
IndexError: list index out of range

2要素の位置は0と1です。最後の行を検索する前に、問題の行で変数の値と型を print() やデバッガーで確認しましょう。

02

想定できる失敗を処理する

割り算PYTHON
try:
    left = int(input("割られる数: "))
    right = int(input("割る数: "))
    answer = left / right
except ValueError:
    print("整数で入力してください")
except ZeroDivisionError:
    print("0では割れません")
else:
    print(f"答え: {answer}")
finally:
    print("計算を終了します")

else は例外がなかった場合、finally は成功・失敗にかかわらず実行されます。すべての処理を大きなtryで囲まず、失敗し得る最小範囲へ限定します。

03

不正な値を例外で知らせる

関数が受け付けられない値を受け取ったら、raise で呼び出し側へ明確に知らせられます。

値を検証するPYTHON
def calculate_price(price: int, count: int) -> int:
    if price < 0:
        raise ValueError("価格は0以上にしてください")
    if count < 1:
        raise ValueError("個数は1以上にしてください")
    return price * count
例外と通常の分岐 商品が見つからないなど通常起こり得る状態は None を返す設計もあります。何を例外とするかは関数の役割と利用側の期待で決めます。
04

期待する結果を小さく確認する

assertPYTHON
def add_tax(price: int) -> int:
    return round(price * 1.1)


assert add_tax(1000) == 1100
assert add_tax(0) == 0
print("確認できました")

assert は開発中の前提確認に便利ですが、実行オプションで無効化できます。利用者入力の検証にはifと例外を使い、自動テストにはテスト用の仕組みを使います。

05

unittestで自動テストする

標準ライブラリの unittest なら追加インストールなしでテストを始められます。

test_price.pyPYTHON
import unittest


def add_tax(price: int) -> int:
    return round(price * 1.1)


class PriceTest(unittest.TestCase):
    def test_add_tax(self):
        self.assertEqual(add_tax(1000), 1100)
        self.assertEqual(add_tax(0), 0)

    def test_negative_price(self):
        self.assertLess(add_tax(-100), 0)


if __name__ == "__main__":
    unittest.main()
実行COMMAND
python3 -m unittest test_price.py
成功時の例OUTPUT
..
----------------------------------------------------------------------
Ran 2 tests

OK
PRACTICE

ミニ課題:割引計算のテスト

金額と割引率を受け取る関数を作り、通常値、0円、範囲外の割引率をテストしてください。割引率が0~100以外なら ValueError を発生させます。

境界値 0、1、99、100、101のように、条件が切り替わる直前・ちょうど・直後を試すと漏れを見つけやすくなります。