Yomiage
メニュー

Python実践講座 11:unittestとデバッグで振る舞いを固定する

更新 2026/9/27 6:22:11 公開

投稿者: しゅりりん

到達点は、正常系だけでなく境界と失敗を再現するテストを書くことです。前提は第06・10回です。

期待結果は仕様から選ぶ

テストは実装をなぞるためでなく、利用者との契約を守るために書きます。「5000円以上なら送料無料」なら、4999と5000が重要です。実装と同じ式で期待値を計算すると、同じ誤りを見逃す場合があります。

次をtest_fees.pyに保存します。

import unittest


def shipping(amount: int) -> int:
    if amount < 0:
        raise ValueError("negative amount")
    return 0 if amount >= 5000 else 500


class ShippingTest(unittest.TestCase):
    def test_boundary(self):
        for amount, expected in [(0, 500), (4999, 500), (5000, 0)]:
            with self.subTest(amount=amount):
                self.assertEqual(shipping(amount), expected)

    def test_negative_is_rejected(self):
        with self.assertRaises(ValueError):
            shipping(-1)


if __name__ == "__main__":
    unittest.main()

python -m unittest -v test_fees を実行すると二つのテストが成功します。subTestを使うと、どの入力で失敗したかが分かります。テスト対象は準備、操作、検証の順で読み取れるようにします。

失敗したテストから小さく調べる

条件をわざと amount > 5000 に変え、5000のケースで失敗することを確認してから元に戻します。テストが本当に変更を検知するかを見る方法です。

デバッグではtracebackの最後の例外名と、自分のコードの該当行を確認します。必要なら breakpoint() で止め、pdbから変数や呼び出し元を調べます。あちこちを書き換える前に、最小の失敗入力を残してください。

単体テストは小さな判断、統合テストはファイルやDBとの接続、CLIテストは終了コードや出力を確かめます。外部サービスを毎回呼ぶテストは不安定になりやすいため、差し替え可能な境界やローカルサーバーを使います。時間に依存する処理には基準時刻を渡します。

練習と解答

練習:空の保存ファイルと壊れた保存ファイルは、同じ期待結果にすべきでしょうか。

解答:保存形式次第です。空のJSONファイルは有効な空配列ではないので、普通は破損として区別します。「読めなければ空を返す」実装をテストが追認しないよう、仕様から期待結果を決めます。

公式資料

unittestとpdbを参照できます。


Python全20回の目次 | 前の回 | 次の回

このブラウザでは Web Speech API が利用できません。

1 / 17 · 停止中