pytestのテスト関数を、クラスを使って書いてみた

pytestでクラスを使う

pytestではテストをクラスにまとめることができます。 テストをクラスにまとめてグループ化することで、テストの構造が明確になります。
また、共通のsetupをクラスレベルで管理できるようになり、 @pytest.fixtureを使ってセットアップを一度だけ記述することでコードの重複を避けることができます。

環境

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

テストを書くための、外部APIをたたくコードを用意しました。

class APIClient:
    def __init__(self, url: str):
        self.url = url

    def get_status(self):
        try:
            response = requests.get(self.url)

            return response.json()
        except RequestException as e:
            raise HTTPException(status_code=500, detail=str(e))

    def check_capacity(self):
        status = self.get_status()
        if status["capacity"] == "Full":
            return "No capacity"
        elif status["capacity"] == "Available":
            return "Capacity available"
        else:
            return "Status check failed"

pytestを書いてみる

import pytest
from main import APIClient


class TestAPIClient:

    @pytest.fixture(autouse=True)
    def setup(self, mocker):
        self.client = APIClient("http://test")
        self.mock_get_status = mocker.patch.object(
            self.client, "get_status", autospec=True
        )

    def test_check_capacity_full(self):
        self.mock_get_status.return_value = {"capacity": "Full"}
        assert self.client.check_capacity() == "No capacity"

    def test_check_capacity_available(self):
        self.mock_get_status.return_value = {"capacity": "Available"}
        assert self.client.check_capacity() == "Capacity available"

    def test_check_capacity_failed(self):
        self.mock_get_status.return_value = {"capacity": "Unknown"}
        assert self.client.check_capacity() == "Status check failed"

注意点

継承を使って凝ったことをしようとすると、メンテナンスが複雑になるので、グループ化を目的とすることにとどめておくことが推奨されています。

参考

テスト駆動Python 第2版(Brian Okken 株式会社クイープ 株式会社クイープ 安井 力)|翔泳社の本