From 442b519fb2385000022a5a65b570b10466d66c6f Mon Sep 17 00:00:00 2001 From: Blake_G <458994951@qq.com> Date: Mon, 28 Jul 2025 02:17:27 +0800 Subject: [PATCH 1/2] feat: add comprehensive custom API tests - Add TestCustomAPI class with multiple test scenarios - Include parametrized tests for different item IDs - Add fixture examples for reusable test data - Test both valid and invalid input validation - Cover GET, POST endpoints with success/error cases --- tests/test_custom_api.py | 154 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 tests/test_custom_api.py diff --git a/tests/test_custom_api.py b/tests/test_custom_api.py new file mode 100644 index 000000000..122a0116b --- /dev/null +++ b/tests/test_custom_api.py @@ -0,0 +1,154 @@ +""" +自定义API测试 +这是一个示例测试文件,展示如何在FastAPI项目中编写测试 +""" +import pytest +from fastapi import FastAPI +from fastapi.testclient import TestClient +from pydantic import BaseModel +from typing import Optional + + +# 创建一个简单的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"] From e6164a272bb2918f15ebc7d69d216ff81dc4e6ef Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 27 Jul 2025 18:30:55 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20for?= =?UTF-8?q?mat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_custom_api.py | 48 ++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/tests/test_custom_api.py b/tests/test_custom_api.py index 122a0116b..147db0beb 100644 --- a/tests/test_custom_api.py +++ b/tests/test_custom_api.py @@ -2,12 +2,13 @@ 自定义API测试 这是一个示例测试文件,展示如何在FastAPI项目中编写测试 """ + +from typing import Optional + import pytest from fastapi import FastAPI from fastapi.testclient import TestClient from pydantic import BaseModel -from typing import Optional - # 创建一个简单的FastAPI应用用于测试 app = FastAPI() @@ -53,32 +54,28 @@ 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 - } + 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() @@ -86,35 +83,38 @@ class TestCustomAPI: 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), - ]) + + @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 + "is_offer": True, } response = client.post("/items/", json=invalid_data) assert response.status_code == 422 # 验证错误 @@ -139,11 +139,7 @@ def test_openapi_schema(): @pytest.fixture def sample_item(): """测试用的示例商品数据""" - return { - "name": "Sample Item", - "price": 50.0, - "is_offer": False - } + return {"name": "Sample Item", "price": 50.0, "is_offer": False} def test_with_fixture(sample_item):