基礎から学ぶPython入門 90日コース | 実践開発 - Day 79:テスト

Python 90日で身につけるPython
スポンサーリンク
スポンサーリンク

Day 79:テスト ― 「コードがちゃんと動くか、自分以外にも証明してみる」

Day 79では、実践開発で欠かせないテーマ、

  • テストとは
  • pytest
  • テストケース
  • 正常系
  • 異常系

をじっくり扱っていきます。

「テスト」と聞くと、 ちょっと堅苦しいイメージがあるかもしれませんが、 開発の世界ではむしろ、

「未来の自分を助けてくれる、優しい仕組み」

という側面がとても大きいです。

テストとは ― 「動いている“つもり”を、ちゃんと確認すること」

なぜテストが必要なのか

コードを書いているとき、 こんな経験はありませんか。

  • さっきまで動いていたのに、急に動かなくなった
  • ちょっと修正したら、別のところが壊れた
  • 「ここは大丈夫だろう」と思っていた部分が、実はバグだらけだった

人間の頭だけで「ちゃんと動いているはず」と信じるのは、 どうしても限界があります。

そこで登場するのが テスト です。

テストは一言で言うと、

「コードが期待通りに動くかどうかを、機械的にチェックする仕組み」

です。

  • 入力を与える
  • 出力を確認する
  • 期待した結果と違えば「おかしい」と教えてくれる

という、冷静な相棒 のような存在です。

テストを書くメリット

テストを書くと、こんな良いことがあります。

  • ちょっと修正しても、「他のところが壊れていないか」をすぐ確認できる
  • バグを早めに見つけられる
  • チーム開発で、「この機能はこう動くべき」という共通認識を持てる
  • 自分のコードに対して、少し誇りが持てる

特に、Day 75までで作ってきたようなAPIやCLIアプリは、 テストがあるかどうかで 安心感がまるで違う ようになってきます。

pytestとは ― 「Pythonテストの定番ツール」

pytestの立ち位置

Pythonの世界には、いくつかテストフレームワークがありますが、 その中でもよく使われるのが、

pytest

です。

特徴をざっくり挙げると、

  • インストールが簡単
  • 書き方がシンプル(関数ベースで書ける)
  • 実行コマンドも分かりやすい(pytest だけ)
  • テストの自動検出(test_*.py*_test.py を探してくれる)

という、初心者にも優しいツールです。

pytestのインストール

まずはインストールから。

bash

pip install pytest

これで、pytest コマンドが使えるようになります。

テスト対象のコードを用意する ― 「小さな関数から始める」

例:足し算と割り算の関数

テストの練習用に、 シンプルな関数をいくつか用意してみましょう。

bash

mkdir day79_test_basic
cd day79_test_basic

bash

cat << 'EOF' > calc.py
def add(a: int, b: int) -> int:
    """
    2つの整数を足し算して返します。
    正常系では、単純に a + b の結果が返ります。
    """
    return a + b


def divide(a: int, b: int) -> float:
    """
    2つの整数を割り算して返します。
    b が 0 の場合は ZeroDivisionError を送出します。
    """
    return a / b
EOF
  • add(a, b):足し算
  • divide(a, b):割り算(0割りは例外)

という、テストしやすい関数です。

テストケースとは ― 「こういう入力なら、こういう結果になるはず」

テストケースの考え方

テストケースは、一言で言うと、

「特定の入力に対して、期待される結果を定義したもの」

です。

例えば、add(a, b) なら、

  • 入力:a = 1, b = 2
    • 期待結果:3
  • 入力:a = -1, b = 5
    • 期待結果:4

などがテストケースになります。

divide(a, b) なら、

  • 入力:a = 10, b = 2 → 期待結果:5.0
  • 入力:a = 10, b = 0 → 期待結果:ZeroDivisionError が発生

というように、

「正常に動くパターン」と「エラーになるパターン」

の両方を考えることが大事です。

正常系と異常系 ― 「うまくいくとき」と「わざと失敗させるとき」

正常系(ハッピーなパターン)

正常系 は、

「想定通りの入力を与えたときに、期待通りの結果が返ってくるか」

を確認するテストです。

例えば add(a, b) なら、

  • add(1, 2)3
  • add(-1, 5)4

などが正常系です。

divide(a, b) なら、

  • divide(10, 2)5.0
  • divide(9, 3)3.0

などですね。

異常系(わざと失敗させるパターン)

異常系 は、

「おかしな入力や、境界的な入力を与えたときに、正しくエラーになるか」

を確認するテストです。

例えば divide(a, b) なら、

  • divide(10, 0)ZeroDivisionError が発生するはず

この「エラーがちゃんと発生するか」をテストするのが、異常系です。

異常系のテストは、

  • セキュリティ的にも重要(変な入力で壊れないか)
  • 信頼性にも重要(予期しない動きにならないか)

という、かなり大事な役割を持っています。

pytestでテストを書く ― 「コードに対して、もうひとつの目を用意する」

テストファイルを作る

pytestでは、 test_*.py という名前のファイルにテストを書くのが一般的です。

calc.py に対するテストを、test_calc.py に書いてみましょう。

bash

cat << 'EOF' > test_calc.py
from calc import add, divide
import pytest


def test_add_normal():
    """
    add 関数の正常系テストです。
    いくつかの入力に対して、期待通りの結果が返るか確認します。
    """
    # 1 + 2 = 3 になるはず
    assert add(1, 2) == 3

    # -1 + 5 = 4 になるはず
    assert add(-1, 5) == 4

    # 0 + 0 = 0 になるはず
    assert add(0, 0) == 0


def test_divide_normal():
    """
    divide 関数の正常系テストです。
    割り算が正しく行われるか確認します。
    """
    # 10 / 2 = 5.0 になるはず
    assert divide(10, 2) == 5.0

    # 9 / 3 = 3.0 になるはず
    assert divide(9, 3) == 3.0


def test_divide_zero_error():
    """
    divide 関数の異常系テストです。
    0で割ったときに ZeroDivisionError が発生するか確認します。
    """
    # divide(10, 0) を呼ぶと ZeroDivisionError が発生するはず
    with pytest.raises(ZeroDivisionError):
        divide(10, 0)
EOF

ここでのポイントを整理すると、

  • テスト関数名は test_ から始める(pytestが自動で見つけてくれる)
  • assert を使って「期待値」と「実際の値」を比較する
  • 異常系では pytest.raises() を使って「例外が発生すること」を確認する

というところです。

テストを実行する

テストファイルができたら、 フォルダ内で pytest を実行してみます。

bash

pytest

うまくいけば、こんな感じの出力になります。

============================= test session starts =============================
collected 3 items

test_calc.py ...                                                        [100%]

============================== 3 passed in 0.03s =============================
  • collected 3 items:3つのテスト関数が見つかった
  • ...:3つとも成功(passed)
  • 3 passed:すべてのテストが通った

という、気持ちのいい結果です。

もしどこかにバグがあれば、 F(failed)やエラーメッセージが表示されます。

正常系・異常系をもう少し深掘りする

正常系テストで意識したいこと

正常系テストでは、

  • 代表的な入力 をテストする
  • 境界値(ギリギリの値)もできればテストする

ことが大事です。

例えば、add(a, b) なら、

  • 小さい値
  • 大きい値
  • 正と負の組み合わせ

などを試しておくと、 「この関数は、だいたいどんな入力でもちゃんと動くな」と 安心しやすくなります。

異常系テストで意識したいこと

異常系テストでは、

  • 明らかにおかしい入力(例:0割り、負の値、空文字など)
  • 仕様上禁止されている入力

に対して、

  • 正しく例外が出るか
  • 変な値を返さないか
  • アプリ全体がクラッシュしないか

を確認します。

異常系テストは、 「攻撃的な入力」や「予期しない使われ方」に対する防御にもつながるので、 セキュリティの観点からもとても重要です。

Day 79ミニテンプレート ― pytest一周セット

最後に、今日の内容をひとまとめにした 「pytest一周練習テンプレート」 を載せておきます。

1. テスト対象のコードを用意する

bash

mkdir day79_test_basic
cd day79_test_basic

bash

cat << 'EOF' > calc.py
def add(a: int, b: int) -> int:
    """
    2つの整数を足し算して返します。
    """
    return a + b


def divide(a: int, b: int) -> float:
    """
    2つの整数を割り算して返します。
    b が 0 の場合は ZeroDivisionError を送出します。
    """
    return a / b
EOF

2. pytest をインストールする

bash

pip install pytest

3. テストファイルを作る(正常系+異常系)

bash

cat << 'EOF' > test_calc.py
from calc import add, divide
import pytest


def test_add_normal():
    assert add(1, 2) == 3
    assert add(-1, 5) == 4
    assert add(0, 0) == 0


def test_divide_normal():
    assert divide(10, 2) == 5.0
    assert divide(9, 3) == 3.0


def test_divide_zero_error():
    with pytest.raises(ZeroDivisionError):
        divide(10, 0)
EOF

4. テストを実行する

bash

pytest
  • すべて passed になればOK
  • わざとバグを入れて、failed を体験してみるのもおすすめ

Day 79のまとめ ― 「テストは、未来の自分への“お守り”」

今日の主役は、

  • テストとは何か:コードが期待通りに動くかを機械的に確認する仕組み
  • pytest:Pythonテストの定番ツール
  • テストケース:入力と期待結果をセットにした「確認の単位」
  • 正常系:うまくいくパターンを確認するテスト
  • 異常系:わざと失敗させて、正しくエラーになるかを見るテスト

でした。

テストを書くのは、 最初は少し面倒に感じるかもしれません。

でも、コードが複雑になればなるほど、

  • 「テストがあるかどうか」で安心感がまるで違う
  • 「テストが通っている」という事実が、心の支えになる
  • 「壊しても、すぐに気づける」という自由さが生まれる

ということを、きっと実感するはずです。

テストは、 ただのチェックではなく、

「未来の自分へのお守り」

でもあります。

Day 79でその入り口に立ったことで、 これからの実践開発は、 より落ち着いて、より誇りを持って、 コードを書き進めていけるようになっていきます。

タイトルとURLをコピーしました