Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

良いテスト

良いテストコードの書き方

実行されたかではなく、実行状態を検証する

関数が呼び出されたことだけ確認すると、

  • 適切な引数で呼ばれてない場合

  • 本当は1回でいいのに2回以上呼ばれてる場合

  • 不要な関数が呼ばれてる場合

に気付けない

# ❌️ 関数が実行されたことを確認するだけ
def test_register_success(mocker):
    notifier = mocker.Mock()
    service = UserService(notifier)
    service.register(success=True)

    # 悪い例:対象が呼ばれたことだけ確認
    # 引数、回数、不要な呼び出しの有無を検証していない
    assert notifier.success.called

不要な関数が呼ばれていないことも検証すべき。

# ⭕️ 相互作用の契約を検証する
def test_register_success(mocker):
    notifier = mocker.Mock()
    service = UserService(notifier)
    service.register(success=True)

    # 適切な引数で、適切な回数呼び出されたことを確認する
    notifier.success.assert_called_once_with(user_id=123)
    # negative assertion: 対象外のものが呼ばれてないことを確認する
    notifier.error.assert_not_called()

他にも、例えばDBからのデータ取得処理を検証したいなら、「欲しいデータが得られている」だけでなく「対象外のデータが得られない」「データを変更しない」ことも検証すべき。

一部ではなく、期待値の全体を検証する

# ❌ フィールド単体しか検証していない
assert result["id"] == 1
assert result["name"] == "Alice"
assert result["role"] == "member"
# ✅ 構造全体を固定する
# 意図しないキーの追加・削除や値の変更も検知できる
assert result == {
    "id": 1,
    "name": "Alice",
    "role": "member",
}


# ✅ フィールド単体に加えて、キーもチェックする
# キーの過不足も検知できる
assert set(result.keys()) == {"id", "name", "role"}

assert result["id"] == 1
assert result["name"] == "Alice"
assert result["role"] == "member"