首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >用 pytest 给项目写第一个测试

用 pytest 给项目写第一个测试

原创
作者头像
dsy
发布2026-08-17 00:05:16
发布2026-08-17 00:05:16
680
举报

上篇说把散落在 routers.pymain.py 两处的 request_id 生成逻辑,收进 app/utils.py 统一成一个函数。抽完之后,我的第一个念头不是「终于干净了」,而是「以后谁改坏了它,我怎么知道」。

这正是今天要补的一环:测试。


一、为什么现在才碰测试

工程项目里,代码会一直变。每改一处,如果只能靠手动发请求去确认没坏,既累又容易漏。

测试把关键行为写成代码,以后每次跑一遍,自动检查这些行为有没有被改坏。

这里有个容易想歪的地方:测试不是为了证明代码永远没 bug,而是为了证明——某些重要行为仍然成立


二、先测最稳的那个函数

我们没有一上来就去测 Agent,也没测大模型调用,而是先测:

代码语言:python
复制
build_request_id()

选它是因为它足够稳定:

  • 不依赖网络
  • 不依赖 API Key
  • 不依赖 DeepSeek
  • 不依赖 FastAPI 服务启动

它只是一个普通 Python 函数,所以最适合当第一个单元测试对象。先拿稳的练手,比一上来调模型容易建立正反馈。


三、单元测试是什么

单元测试,就是测一个很小的代码单元。

今天只测这一行导入:

代码语言:python
复制
from app.utils import build_request_id

不启动服务,不调接口,只验证函数本身的行为。范围越小,出错时越容易定位。


四、两个测试用例

测试文件放在:

代码语言:shell
复制
tests/test_utils.py

内容大概是这样:

代码语言:python
复制
from app.utils import build_request_id


def test_build_request_id_reuses_header_value():
    request_id = build_request_id("debug-001")

    assert request_id == "debug-001"


def test_build_request_id_generates_short_id_when_missing():
    request_id = build_request_id()

    assert isinstance(request_id, str)
    assert len(request_id) == 8

两个测试分别验证:

  • 传入 X-Request-ID 时,应该原样返回
  • 没传入时,应该自动生成 8 位字符串

一个测「有值复用」,一个测「无值生成」,把函数的两条分支都盖住。


五、pytest 怎么找到测试

pytest 会自动发现:

  • tests/ 目录
  • 文件名匹配 test_*.py*_test.py
  • 函数名以 def test_... 开头

所以只要执行:

代码语言:bash
复制
uv run pytest

pytest 就会自动找到测试并运行。预期结果是:

代码语言:shell
复制
2 passed

六、assert 是核心

pytest 里最基础的判断就一句:

代码语言:python
复制
assert request_id == "debug-001"

意思是:我预期实际结果等于 debug-001。不相等,测试就失败。

不需要额外框架,一个 assert 就把「预期」钉死了。


七、这一篇想说清楚一件事

工程化不只是把代码拆得好看,还要能自动验证关键行为。

项目走到这一步,已经从:

代码语言:shell
复制
能跑

进一步走向:

代码语言:shell
复制
能验证

能跑只是 Demo,能验证才开始像工程。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、为什么现在才碰测试
  • 二、先测最稳的那个函数
  • 三、单元测试是什么
  • 四、两个测试用例
  • 五、pytest 怎么找到测试
  • 六、assert 是核心
  • 七、这一篇想说清楚一件事
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档