跳转到内容

构建、测试与分发

DEV-05: 构建、测试与分发

学习目标

  • 理解 pyproject.toml + uv 构建系统与 optional extras
  • 掌握 Makefile 任务与本地开发流程
  • 理解多 Python 版本测试与 snapshot 测试策略
  • 理解 MkDocs 多语言文档管线

项目实践

构建系统与 Optional Extras

项目使用 pyproject.toml + uv 管理依赖与分发:

# 可选 extras 分组
[project.optional-dependencies]
voice = ["websockets>=13.0"]
redis = ["redis>=5.0"]
litellm = ["litellm>=1.50.0"]
any-llm = ["any-llm-sdk>=0.0.3"]

安装方式

Terminal window
# 核心 SDK
pip install openai-agents
# 核心 + 语音支持
pip install 'openai-agents[voice]'
# 核心 + Redis session
pip install 'openai-agents[redis]'
# 全部可选依赖
pip install 'openai-agents[voice,redis,litellm,any-llm]'

Makefile 开发流程

Terminal window
make sync # 安装/刷新开发依赖
make format # ruff 格式化(应用修复)
make lint # ruff lint(仅检查)
make typecheck # mypy + pyright 类型检查
make tests # 运行完整测试套件
make coverage # 生成覆盖率报告(低于阈值会失败)
make snapshots-fix # 修复 inline snapshot
make snapshots-create # 创建新 snapshot
make build-docs # 构建文档
make serve-docs # 本地预览文档

推荐流程

Terminal window
make format && make lint && make typecheck && make tests

多 Python 版本测试

SDK 支持 Python 3.10+。在隔离的 3.10 环境中测试:

Terminal window
UV_PROJECT_ENVIRONMENT=.venv_310 uv sync --python 3.10 --all-extras --all-packages --group dev
UV_PROJECT_ENVIRONMENT=.venv_310 uv run --python 3.10 -m pytest

为什么测试最老版本:Python 3.10 是最低支持版本。如果代码在 3.10 上通过,较新版本大概率兼容。

Snapshot 测试

使用 pytest-snapshot 进行 inline snapshot 测试。某些测试(如模型响应、trace 输出)依赖精确的输出匹配:

  • make snapshots-fix:自动更新 inline snapshot(修复后)
  • make snapshots-create:创建新 snapshot(新增测试时)

双类型检查工具

工具用途
mypy静态类型检查,关注类型标注正确性
pyright更激进的类型推断,捕获 mypy 可能漏掉的问题

双工具增加 CI 开销,但提高类型覆盖率。

MkDocs 多语言文档管线

注意docs/jadocs/kodocs/zh 下的翻译文件是自动生成的,不应手动编辑

问题与规避

问题规避方案
uv 未安装导致依赖安装失败使用 pip install openai-agents 替代
Snapshot 测试在模型更新后全部失败运行 make snapshots-create 重新生成
类型检查在 3.10 与 3.12 表现不同在两个版本上分别运行 make typecheck
翻译文档与英文源文档不同步运行 make build-full-docs 重新生成翻译

设计取舍

为什么选择 uv 而非 pip + requirements.txt

uv 提供极速依赖解析(Rust 实现),在多版本/多平台场景下比 pip 快 10-100 倍。同时 uv 支持 pyproject.toml 原生管理(无需 setup.py),简化了构建配置。

为什么保留双类型检查工具

Mypy 和 pyright 有不同的类型推断策略。Mypy 更保守(需要显式标注),pyright 更激进(推断更多)。两者互补——mypy 保证类型标注的正确性,pyright 捕获推断层面的问题。

代价:CI 时间翻倍。

参考来源