pythonasyncioapiasyncfastapiframeworkjsonjson-schemaopenapiopenapi3pydanticpython-typespython3redocreststarletteswaggerswagger-uiuvicornweb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
4.1 KiB
150 lines
4.1 KiB
"""
|
|
自定义API测试
|
|
这是一个示例测试文件,展示如何在FastAPI项目中编写测试
|
|
"""
|
|
|
|
from typing import Optional
|
|
|
|
import pytest
|
|
from fastapi import FastAPI
|
|
from fastapi.testclient import TestClient
|
|
from pydantic import BaseModel
|
|
|
|
# 创建一个简单的FastAPI应用用于测试
|
|
app = FastAPI()
|
|
|
|
|
|
# 定义数据模型
|
|
class Item(BaseModel):
|
|
name: str
|
|
price: float
|
|
is_offer: bool = False
|
|
|
|
|
|
class User(BaseModel):
|
|
username: str
|
|
email: str
|
|
|
|
|
|
# 定义API路由
|
|
@app.get("/")
|
|
def read_root():
|
|
return {"message": "Hello Custom API"}
|
|
|
|
|
|
@app.get("/items/{item_id}")
|
|
def read_item(item_id: int, q: Optional[str] = None):
|
|
return {"item_id": item_id, "q": q}
|
|
|
|
|
|
@app.post("/items/")
|
|
def create_item(item: Item):
|
|
return {"item": item, "status": "created"}
|
|
|
|
|
|
@app.get("/users/{user_id}")
|
|
def get_user(user_id: int):
|
|
return {"user_id": user_id, "username": f"user_{user_id}"}
|
|
|
|
|
|
# 创建测试客户端
|
|
client = TestClient(app)
|
|
|
|
|
|
# 测试用例
|
|
class TestCustomAPI:
|
|
"""自定义API测试类"""
|
|
|
|
def test_read_root(self):
|
|
"""测试根路径"""
|
|
response = client.get("/")
|
|
assert response.status_code == 200
|
|
assert response.json() == {"message": "Hello Custom API"}
|
|
|
|
def test_read_item_with_params(self):
|
|
"""测试带参数的商品查询"""
|
|
response = client.get("/items/5?q=somequery")
|
|
assert response.status_code == 200
|
|
assert response.json() == {"item_id": 5, "q": "somequery"}
|
|
|
|
def test_read_item_without_params(self):
|
|
"""测试不带查询参数的商品查询"""
|
|
response = client.get("/items/10")
|
|
assert response.status_code == 200
|
|
assert response.json() == {"item_id": 10, "q": None}
|
|
|
|
def test_create_item(self):
|
|
"""测试创建商品"""
|
|
item_data = {"name": "Test Item", "price": 99.99, "is_offer": True}
|
|
response = client.post("/items/", json=item_data)
|
|
assert response.status_code == 200
|
|
response_data = response.json()
|
|
assert response_data["status"] == "created"
|
|
assert response_data["item"]["name"] == "Test Item"
|
|
assert response_data["item"]["price"] == 99.99
|
|
assert response_data["item"]["is_offer"] is True
|
|
|
|
def test_get_user(self):
|
|
"""测试获取用户信息"""
|
|
response = client.get("/users/123")
|
|
assert response.status_code == 200
|
|
assert response.json() == {"user_id": 123, "username": "user_123"}
|
|
|
|
@pytest.mark.parametrize(
|
|
"item_id,expected_id",
|
|
[
|
|
(1, 1),
|
|
(42, 42),
|
|
(999, 999),
|
|
],
|
|
)
|
|
def test_read_item_parametrized(self, item_id, expected_id):
|
|
"""参数化测试:测试不同的商品ID"""
|
|
response = client.get(f"/items/{item_id}")
|
|
assert response.status_code == 200
|
|
assert response.json()["item_id"] == expected_id
|
|
|
|
def test_invalid_item_id(self):
|
|
"""测试无效的商品ID"""
|
|
response = client.get("/items/not_a_number")
|
|
assert response.status_code == 422 # 验证错误
|
|
|
|
def test_create_item_invalid_data(self):
|
|
"""测试创建商品时的无效数据"""
|
|
invalid_data = {
|
|
"name": "Test Item",
|
|
# 缺少必需的price字段
|
|
"is_offer": True,
|
|
}
|
|
response = client.post("/items/", json=invalid_data)
|
|
assert response.status_code == 422 # 验证错误
|
|
|
|
|
|
# 独立的测试函数(不在类中)
|
|
def test_app_startup():
|
|
"""测试应用启动"""
|
|
assert app.title == "FastAPI"
|
|
|
|
|
|
def test_openapi_schema():
|
|
"""测试OpenAPI schema生成"""
|
|
response = client.get("/openapi.json")
|
|
assert response.status_code == 200
|
|
schema = response.json()
|
|
assert "openapi" in schema
|
|
assert "info" in schema
|
|
|
|
|
|
# Fixture示例
|
|
@pytest.fixture
|
|
def sample_item():
|
|
"""测试用的示例商品数据"""
|
|
return {"name": "Sample Item", "price": 50.0, "is_offer": False}
|
|
|
|
|
|
def test_with_fixture(sample_item):
|
|
"""使用fixture的测试"""
|
|
response = client.post("/items/", json=sample_item)
|
|
assert response.status_code == 200
|
|
response_data = response.json()
|
|
assert response_data["item"]["name"] == sample_item["name"]
|
|
|