- 教程
- 云原生
【免费下载链接】learn-to-cloud
A courseware built on the belief that anyone can learn foundational cloud engineering skills with the right guide and discipline
本篇技术指南围绕 learn-to-cloud 课程体系中 docs/phase2/3-fastapi.md 展开,系统讲解 FastAPI 的核心原理、L2C Journal 应用中的技术选型背景,以及以 pytest + httpx 为核心的 API 测试方法论。读完本文,你将掌握基于 Python 类型提示定义端点、使用 Pydantic 校验请求/响应、借助
conftest.py组织测试夹具,并能在真实项目(如课程 Capstone 中的 Journal API)中编写和运行完整测试套件。
FastAPI 是什么:L2C Journal 的 API 技术底座
FastAPI 是一个现代化、高性能(fast)的 Python Web 框架,用于构建 API 服务,它基于 Python 3.6+ 的标准类型提示(type hints)体系工作。与传统的 Web 框架相比,它的核心优势在于:
- 类型驱动:利用 Python 的 type hints 同时完成数据校验、序列化与 API 文档生成,一份类型定义多处复用;
- 自动文档:框架内置 Swagger UI 等交互式文档界面,无需额外配置即可看到可调试的 API 页面;
- 异步友好:原生支持
async/await异步代码路径,适合对接 LLM API、数据库等 IO 密集型服务。
在 learn-to-cloud 课程中,FastAPI 是构建L2C Journal 应用(Phase 2 Capstone 的日记/学习日志分析应用)所采用的框架,你后续也将使用它。这门课程预计花费3–4 天完成本主题,核心学习路径是官方 FastAPI 教程,重点目标是"能独立创建一个 FastAPI 应用并定义端点"。
在课程体系中的定位
FastAPI 主题是 Phase 2(编程与 AI 集成)的第 3 个主题,位于 REST API 基础之后、数据库与 GenAI API 之前。从 docs/phase2/README.md 的课程表可以看到完整脉络:
| 序号 | 主题 | 与本主题的关系 |
|---|---|---|
| 1 | Python | 提供 pytest 等测试工具的语言基础 |
| 2 | APIs | 铺垫 REST 资源、HTTP 方法、状态码等概念 |
| 3 | FastAPI(本主题) | 用框架落地 REST API,并学会测试 |
| 4 | Databases | 为 Journal 应用接入持久化存储 |
| 5 | GenAI APIs | 为 Journal 应用接入 LLM 情感分析与摘要 |
| 6 | Prompt Engineering | 设计 /analyze 端点使用的提示词 |
其中 REST API 主题(docs/phase2/2-api.md)要求你理解 GET、POST、PUT、DELETE 的语义以及 200、201、400、404、500 等状态码的含义——这些正是后续 FastAPI 测试中验证的重点对象。Phase 3 与 Phase 4 还会把同一个 Journal API 依次部署到云 VM(docs/phase3/9-deploy-api.md)、容器化并接入 CI/CD 与监控(docs/phase4/6-build-app.md、docs/phase4/5-monitoring.md),因此本主题打下的测试基础会被反复复用。
你需要掌握的 FastAPI 核心能力
课程 Checklist 要求你在进入下一主题前,至少掌握以下六项能力:
1. 创建带基础端点的 FastAPI 应用
一个最小应用通常包含FastAPI()实例、若干路径装饰器和返回 JSON 的响应函数,例如:
from fastapi import FastAPI app = FastAPI() @app.get("/") def read_root(): return {"message": "Hello L2C"}配合 ASGI 服务器(如 uvicorn)即可本地启动并访问。
2. 路径参数(Path Parameters)与查询参数(Query Parameters)
- 路径参数:URL 路径中的变量段,如
/entries/{entry_id},通过函数参数接收; - 查询参数:URL 中
?key=value形式,未在路径中声明、带默认值的函数参数即成为查询参数。
两者均可配合类型提示获得自动校验与文档展示。
3. 用 Pydantic 模型校验请求与响应
FastAPI 的数据校验由 Pydantic 完成。定义一个继承BaseModel的类,即可声明请求体结构;FastAPI 会在请求进入时自动校验,非法数据直接返回 422 校验错误,合法数据则转换为对应模型实例。这也是本主题测试部分用pytest.raises(ValidationError)验证的重点。
4. 理解 FastAPI 的自动文档(Swagger UI)
基于类型提示与 Pydantic 模型,FastAPI 自动生成交互式 API 文档。你可以直接在浏览器中查看所有端点、请求/响应结构,并在线发起调用——这是课程 Checklist 中明确要求理解的特性。
5. 依赖注入(Dependency Injection)
通过Depends声明依赖(如共享数据库会话、认证逻辑、测试客户端),可将横切逻辑从端点中抽离,也便于在测试中用覆盖件替换真实依赖。
6. 异步代码支持
FastAPI 原生支持async def端点,课程中的 Capstone 项目正是使用httpx.AsyncClient做异步测试,以获得更好的测试性能。异步能力同样应用于后续对接 LLM API(docs/phase2/5-genai-apis.md 明确将异步支持列为关键概念之一)。
测试 FastAPI 应用:pytest + httpx 实战
本主题的核心实践章节围绕API 测试展开。你在 Python Crash Course 中已经学过 pytest 基础,现在把这些知识迁移到 API 测试场景。在 Phase 2 的 Capstone 项目中,你将运行一套完整的测试套件来验证实现是否正确——这也是后续云部署、CI/CD 流水线的质量闸门。
测试技术栈与关键概念
| 概念 | 作用 |
|---|---|
httpx.AsyncClient | 以异步方式发起 HTTP 请求,测试异步 API 端点,性能更好 |
conftest.py中的 Fixtures | 提供共享测试环境:测试客户端、样例数据、数据库清理等 |
| HTTP 方法测试 | 覆盖 GET、POST、PATCH、DELETE 的完整 CRUD 路径 |
| 响应断言 | 检查状态码与 JSON 内容是否符合预期 |
| Pydantic 模型验证测试 | 例如用pytest.raises(ValidationError)断言非法输入被拒绝 |
pytest.skip() | 跳过尚未实现功能的测试,保持测试套件可先行通过 |
1. 使用httpx.AsyncClient测试异步端点
httpx是 FastAPI 官方测试教程推荐使用的 HTTP 客户端,其AsyncClient天然适配 FastAPI 的异步特性。典型用法是利用ASGITransport直接驱动应用实例,无需启动真实服务器:
import pytest from httpx import ASGITransport, AsyncClient from main import app @pytest.mark.anyio async def test_read_root(): transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: response = await client.get("/") assert response.status_code == 200要点说明:
- 测试函数标记为异步(
async def),配合anyio等插件运行; ASGITransport让请求在进程内直接进入应用,测试既快又无需网络端口;- 课程特别强调使用
AsyncClient的动机是性能——异步测试可以并发执行多个请求,显著加快大型测试套件的运行。
2. 在conftest.py中组织共享 Fixtures
conftest.py是 pytest 的共享配置与夹具(fixture)文件,放在测试目录根级后,其定义的 fixture 可被该目录下所有测试文件自动使用。课程要求理解并实践三类典型 fixture:
- 测试客户端:预配置好的
AsyncClient,各测试用例直接注入使用,避免重复创建; - 样例数据:固定的输入/期望输出,保证断言可重复;
- 数据库清理:在每个用例前创建、用例后清理数据库状态,隔离测试间数据污染。
一个精简示例:
# conftest.py import pytest from httpx import ASGITransport, AsyncClient from main import app @pytest.fixture async def client(): transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as c: yield c # 每个用例结束后自动关闭 @pytest.fixture def sample_entry(): return {"title": "My first endpoint", "content": "Learned FastAPI today"}3. 测试不同 HTTP 方法与响应断言
Journal API 的完整 CRUD 对应四种方法:创建用 POST、读取用 GET、局部更新用 PATCH、删除用 DELETE。测试时不仅调用方法,更要断言两件事:状态码是否符合语义(200/201/204 等成功码,400/404/422 等错误码),以及JSON 内容是否包含预期字段与取值。
async def test_create_entry(client, sample_entry): response = await client.post("/entries", json=sample_entry) assert response.status_code == 201 data = response.json() assert data["title"] == sample_entry["title"] async def test_get_entry(client): response = await client.get("/entries/1") assert response.status_code == 200 assert "content" in response.json()4. 测试 Pydantic 模型验证
Pydantic 校验逻辑本身也是可测试的。对非法数据(缺失必填字段、类型错误、超出约束的值),可以直接断言模型抛ValidationError:
import pytest from pydantic import ValidationError from models import JournalEntry def test_invalid_entry_rejected(): with pytest.raises(ValidationError): JournalEntry(title="", content="") # 例如空字符串违反约束这确保 API 的输入防线在端点层面之外依然成立,也是课程 AI 测验题"如何测试 Pydantic 模型对非法数据抛出 ValidationError"的标准答案。
5. 用pytest.skip()处理未实现功能
在 Capstone 开发过程中,功能往往分阶段完成。对尚未实现的端点,可用pytest.skip()让测试优雅跳过而不是报错,保持测试套件整体可运行、可增量推进:
def test_analyze_endpoint(): pytest.skip("AI analysis endpoint not implemented yet")运行测试
在 Capstone 项目中,运行全部测试:
pytest运行指定测试文件:
pytest tests/test_api.py pytest tests/test_models.pypytest默认递归收集test_*.py/*_test.py文件,并自动加载conftest.py中的夹具配置。课程建议把 API 测试与模型测试拆分到不同文件(如tests/test_api.py、tests/test_models.py),便于单独运行与定位失败。
测试 Journal API 的 AI 分析端点
Phase 2 Capstone 的核心功能之一是/analyze端点:把日记文本发送给 LLM,返回情感倾向(positive/negative/neutral)与两句摘要。这在 docs/phase2/5-genai-apis.md 与 docs/phase2/6-prompt-engineering.md 中有完整的提示词设计范式(结构化 JSON 输出、temperature 控制、few-shot 示例等)。
针对该端点的测试策略要点:
- Mock 外部 LLM 调用:真实 LLM API 按量计费且结果不确定,测试中应使用 fixture 替换(monkeypatch)LLM 客户端,返回固定 JSON,从而断言端点正确转发与解析;
- 验证结构化输出:LLM 返回的
sentiment/summary必须经 Pydantic 模型校验后返回给前端,非法输出应触发ValidationError路径; - 环境变量注入:LLM API Key 通过环境变量注入(docs/phase2/5-genai-apis.md 明确要求"绝不把密钥提交进 git"),测试 fixture 可注入临时假 Key。
这样的测试不仅覆盖业务逻辑,也为 Phase 4 的监控埋下伏笔——docs/phase4/5-monitoring.md 要求用prometheus_client对 FastAPI 应用插桩,跟踪/analyze端点的延迟、错误率与 token 用量。
从测试到生产:测试套件的后续价值
本主题的测试能力将在课程后续阶段反复被调用:
- Phase 3 部署验证:云部署 Capstone(docs/phase3/9-deploy-api.md)的成功标准之一就是"所有 CRUD 操作经由 API 端点正常工作"——本主题的测试套件正是这一验收的自动化手段;
- Phase 4 CI/CD:DevOps Capstone(docs/phase4/6-build-app.md)要求"每次提交时构建并测试应用",
pytest测试套件会接入流水线,作为镜像构建与部署的前置检查; - Phase 4 容器化:同一 Capstone 要求将 Journal API 容器化(Dockerfile),本地先构建并运行容器验证功能——验证手段同样依赖本主题的测试。
换言之,现在写下的每一个断言,都是未来云上生产环境的验收标准。
AI 助手测验:用提示词检验你的掌握程度
完成学习后,可以用下面的提示词让 AI 助手对你进行提问与考察(覆盖本主题全部核心概念):
- 你能请我解释一下什么是 FastAPI 以及它是如何工作的吗?
- 你能考考我如何创建一个 FastAPI 应用并定义端点吗?
- 你能请我解释如何在 FastAPI 中处理请求和响应模型吗?
- 你能请我解释如何在 FastAPI 中使用路径参数和查询参数吗?
- 你能考考我如何在 FastAPI 中使用依赖注入吗?
- 你能请我解释如何在 FastAPI 中使用 Pydantic 模型吗?
- 你能请我解释如何在 FastAPI 中使用异步代码吗?
- 你能考考我 pytest fixtures 是如何工作的、
conftest.py是做什么的吗? - 你能请我说明如何测试 Pydantic 模型对非法数据抛出
ValidationError吗?
建议让 AI 一次只问一题、在你答错时引导而非直接给答案,模拟真实面试场景。
主题完成清单
进入下一主题前,请逐项确认你都能回答"是":
- 我能创建一个带基础端点的 FastAPI 应用
- 我理解路径参数与查询参数
- 我能使用 Pydantic 模型校验请求与响应
- 我理解 FastAPI 的自动文档(Swagger UI)
- 我理解 pytest fixtures 与
conftest.py的用法 - 我能用
pytest运行测试并解读结果
继续前进
本主题属于 Phase 2(编程与 AI 集成)的第 3 步。完成 FastAPI 构建与测试后,接下来将进入数据库主题为 Journal 应用接入持久化存储,随后是 GenAI API 集成与提示词工程,最终完成带 AI 分析的 Journal Capstone。整阶段目标与进度可对照 Phase 2 总览查看。
- 教程
- 云原生
【免费下载链接】learn-to-cloud
A courseware built on the belief that anyone can learn foundational cloud engineering skills with the right guide and discipline
相关推荐
mcp-for-beginners 实战:用 TypeScript 构建、运行并测试你的第一个 MCP 服务器
mcp for beginners 实战:用 TypeScript 构建、运行并测试你的第一个 MCP 服务器 本文聚焦于 mcp for beginners
教程文档人工智能使用 .NET 构建并测试你的第一个 MCP 服务器:从 `dotnet run` 到 MCP Inspector 实战
使用 .NET 构建并测试你的第一个 MCP 服务器:从 dotnet run 到 MCP Inspector 实战 本篇技术指南以 mcp for begin
教程文档人工智能FastAPI 第一步:从零创建、运行并理解你的第一个 API 应用
FastAPI 第一步:从零创建、运行并理解你的第一个 API 应用 FastAPI 的入门门槛极低——一个文件、几行代码即可得到一个带自动文档与 OpenAP
后端Web框架API设计
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考