LoginSignup
2
5

More than 1 year has passed since last update.

[Python]FastAPIテスト方法 メモ

Posted at
  • Python WebAPI開発用フレームワークFastAPIを使用して作成したAPIのテスト方法についてメモする。

大まかなテストコードの書き方

  1. TestClient をインポートする。

  2. TestClient を作成し、FastAPIに渡す。

  3. test_ 始まりの名前の関数を作成する (pytest 仕様)。

  4. TestClient オブジェクトを使用し、テスト用リクエストを記述する。

  5. チェック内容の assert 文を記述する。

事前準備

  • pytestインストール
  pip install pytest

コード

テスト対象

  • main.py
    • ユーザー情報の登録・取得を行うAPI
from fastapi import FastAPI, Header, HTTPException
from pydantic import BaseModel

# 正常トークン
correct_token = "correct_token"

# 模擬ユーザーデータ
dummy_user_db = {
    "abcde12345": {"id": "abcde12345", "name": "Yamada", "email_address": "yamada@example.com"},
    "fghij67890": {"id": "fghij67890", "name": "Tanaka", "email_address": "tanaka@example.com"},
}

app = FastAPI()


class User(BaseModel):
    id: str
    name: str
    email_address: str

# ユーザー情報取得API
@app.get("/users/{user_id}", response_model=User)
async def get_user(user_id: str, token: str = Header(...)):
    # トークン不正時
    if token != correct_token:
        raise HTTPException(
            status_code=400, detail="token_verification_failed")
    # ユーザー非存在時
    if user_id not in dummy_user_db:
        raise HTTPException(status_code=404, detail="user_not_found")
    return dummy_user_db[user_id]


# ユーザー情報登録API
@app.post("/users/", response_model=User)
async def create_user(user: User, token: str = Header(...)):
    # トークン不正時
    if token != correct_token:
        raise HTTPException(
            status_code=400, detail="token_verification_failed")
    # ユーザーID重複時
    if user.id in dummy_user_db:
        raise HTTPException(status_code=400, detail="user_id_duplicated")
    dummy_user_db[user.id] = user
    return user

テストコード

  • 各APIの正常/異常系リクエスト時のレスポンスを検証する。
from fastapi.testclient import TestClient

from main import app

client = TestClient(app)


# ユーザー情報取得API 正常系テスト
def test_get_user_NR001():
    response = client.get(
        "/users/abcde12345", headers={"token": "correct_token"})
    # レスポンス検証
    # ステータスコード
    assert response.status_code == 200
    # レスポンスボディ
    assert response.json() == {
        "id": "abcde12345",
        "name": "Yamada",
        "email_address": "yamada@example.com",
    }

# ユーザー情報取得API 異常系テスト
# トークン違い
def test_get_user_ABR001():
    response = client.get("/users/abcde12345",
                          headers={"token": "dummy_token"})
    assert response.status_code == 400
    assert response.json() == {"detail": "token_verification_failed"}

# ユーザー情報取得API 異常系テスト
# 存在しないユーザー指定
def test_get_user_ABR002():
    response = client.get(
        "/users/hogefuga", headers={"token": "correct_token"})
    assert response.status_code == 404
    assert response.json() == {"detail": "user_not_found"}

# ユーザー情報登録API 正常系テスト
def test_create_user_NR001():
    # 正常系リクエスト
    # ヘッダーとボディは辞書型で渡す。
    response = client.post(
        "/users/",
        headers={"Token": "correct_token"},
        json={"id": "klmno12345", "name": "Kobayashi",
              "email_address": "kobayashi@example.com"},
    )
    assert response.status_code == 200
    assert response.json() == {
        "id": "klmno12345",
        "name": "Kobayashi",
        "email_address": "kobayashi@example.com",
    }

# ユーザー情報登録API 異常系テスト
# トークン違い
def test_create_user_ABR001():
    response = client.post(
        "/users/",
        headers={"Token": "dummy_token"},
        json={"id": "klmno12345", "name": "Kobayashi",
              "email_address": "kobayashi@example.com"},
    )
    assert response.status_code == 400
    assert response.json() == {"detail": "token_verification_failed"}


# ユーザー情報登録API 異常系テスト
# 登録済みユーザーID指定
def test_create_user_ABR002():
    response = client.post(
        "/users/",
        headers={"Token": "correct_token"},
        json={
            "id": "abcde12345",
            "name": "Kobayashi",
            "email_address": "kobayashi@example.com"
        },
    )
    assert response.status_code == 400
    assert response.json() == {"detail": "user_id_duplicated"}

動作確認

pytest
================================================================ test session starts ================================================================
platform win32 -- Python 3.8.3, pytest-6.2.3, py-1.10.0, pluggy-0.13.1
rootdir: C:\Users\user\Documents\dev\vscode\ws_git\fastapi\test
plugins: anyio-3.2.1, cov-2.11.1
collected 6 items

test_main.py ......                                                                                                                            [100%]

================================================================= 6 passed in 0.56s =================================================================

参考情報

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5