面试被问“你们接口测试怎么做的”,我卡了三次:聊聊我写的1300条用例最后为什么砍到210条

🔑 关键词:接口测试,契约测试,pytest接口自动化,接口测试用例设计,Postman

📖 摘要:一个写了8个月接口自动化的人,回头翻了1300条用例只找到37条真正拦下过问题的。这篇文章讲断言该分几层、契约测试到底值不值得上、造数据的三条路各自什么代价,以及并发/幂等/越权这些专坑接口测试的场景怎么测。没有框架搭建教程,全是踩过的坑和具体的取舍。

面试被问“你们接口测试怎么做的”,我卡了三次

图片

去年面一家公司,技术面问我接口测试怎么做。我说用 Postman 调,核心的用 pytest 写成自动化。面试官点点头,接着问:"那你说一个你自动化跑出来的线上问题。"

我卡住了。

回去翻了翻我们那套跑了 8 个月的用例库,1300 条,Allure 报告挺好看的,绿的。但真要说哪条用例把线上问题拦下来了……我翻了大半天,只找到 37 条。

先说那 1300 条是怎么来的

大部分是这么攒出来的:研发提测,打开接口文档,把每个接口的每个参数组合抄一遍,断言写 assert res.status_code == 200,有的稍微好点,加一句 assert res.json()["code"] == 0。

890 条用例只有这两行断言。跑一次 47 分钟(单进程 requests 串行),后来加了 pytest-xdist,-n 8 压到 6 分半,看着挺爽,实际一点用没有。

2019 年那次大重构,研发把 userId 改成 user_id,300 多条用例红了。我们花了两天改用例,改完全绿,交付。整个过程没发现一个缺陷——我们只是在给研发的字段改名打工。

那 37 条真正有用的用例,我后来单独建了个目录存着。它们有个共同点:断言的不是接口返回了什么,而是数据变成什么样了。

断言只写 200,等于做了一场仪式

图片

我现在写接口用例,习惯分几层看,你可以对着自己的用例库数数:

  • HTTP 状态码(这一层最没用,但少了不行)
  • 业务 code,比如 0 成功 / 10001 参数错 / 40003 无权限
  • 关键字段值——注意是"关键",不是全字段
  • JSON Schema 校验,类型、必填、枚举范围。这个能拦住"字段从 number 变成 string"这种静默事故
  • 数据库落库校验。请求成功不代表数据对了
  • 下游副作用。MQ 有没有发出去、Redis 的 key 写没写、第三方 mock 有没有被调到

举个真实的:下单接口返回 {"code":0,"msg":"success"},一切正常。DB 里订单表有一条记录,状态 0(待支付)。但库存表 stock 字段没减。

只看 response,你测一辈子也发现不了这个。这个 bug 是研发漏了事务里的一步,第二天财务对账才发现。

我把这六层写进团队的用例规范之后,用例总数从 1300 降到 210,跑一次 1 分 50 秒。缺陷发现数没降。

(当然也有代价,写一条这种用例的时间大概是原来的三倍。我们后来只在核心链路上这么干,边缘接口还是放养。)

契约测试:别神化它,但也别不认识它

字段改名这种事,其实是契约测试要解决的问题。

Pact 的思路是消费者驱动:消费方写清楚"我需要你这个接口返回什么",生成一个 pact 文件推到 broker,提供方在 CI 里跑 verification,对不上就挂。

图片

我们试过。Pact 的 provider verification 要写 providerStates,就是"我这个用例需要数据库里先有一笔什么什么订单",这玩意儿写起来比用例本身还长。三个人以下的团队,我不建议碰,维护成本盖过收益。

后来我们换了个土办法:把每个核心接口的响应 JSON Schema 存在 Git 仓库里,一个接口一个 .json 文件,一共 50 多个。研发要改字段,得先改 Schema——他改了 Schema,消费方的 CI 才会红,PR 里 reviewer 一眼能看见。

这不算严格意义的契约测试,但它把"接口变更"这件事从口头通知变成了代码可见。对我们这种二十来人的团队,够用了。

(pact broker 的 webhook 我配了两次才通,头一回是因为回调地址写成了 localhost,这个坑我到现在还记得。)

几种工具,我用下来的真实感受

Postman / Newman:上手半天,谁都能用。但 pm.test 断言链一多就难维护,collection 超过 200 个请求之后界面开始卡。适合手工调试和几十条冒烟,别拿它当自动化框架。

pytest + requests + allure:我现在的主力。conftest.py 里放一个 session 级的 fixture 复用一个 token,省掉每次请求都登一次。参数化用 @pytest.mark.parametrize 接 yaml,改数据不用改代码。缺点是要会写 Python,团队里没人会就白搭。

JMeter:压测确实强,梯度加压、TPS 曲线都很清楚。但拿它做功能测试是自虐,JSR223 写断言调试起来想砸键盘,CSV Data Set Config 一并发就读串了。

Karate:DSL 写起来确实优雅,还自带 mock server。但报错信息基本靠猜,新人排查半天不知道错在哪一行。

图片

我的组合是:Postman 调接口 + pytest 做回归 + JMeter 做压测。别指望一个工具干三件事。

真正的瓶颈根本不是框架,是造数据

搭框架这事,一个熟练的人三天能搭完。让你头疼三个月的是数据。

造数据我们试过三条路:

调接口造。慢,一个用户要先注册、登录、实名、绑卡,七步才到能下单的状态。但真实,走的是真校验。

直连 DB 造。快,INSERT 几条就完事。但绕过了所有业务校验,容易造出脏数据,比如状态字段塞了个 99,接口直接 500,你还以为是 bug。

影子库。Docker 起个 MySQL,恢复一份 2.3G 的 dump,90 秒。干净,但每次都要重来,且从生产导出的数据和测试环境表结构有延迟。

最后我们是混着用:pytest 的 fixture 里开一个事务,用例跑完 rollback。对纯读写的表很好使。但只要有 MQ 的接口就回滚不了——消息已经发出去了,撤不回来。

图片

所以你别指望着一个方案解决所有问题,这句话我是在踩了半年坑之后才真正理解的。

几个专坑接口测试的场景,都是我被坑过的

签名。sign = md5(appid + timestamp + nonce + secret),服务端校验 timestamp 和服务器时间差超过 5 分钟直接拒。压测机上 NTP 没同步,50 个并发全红,查了两小时才反应过来不是接口的问题。

Token 过期。access_token 两小时,refresh_token 七天。用例跑到第 80 条突然全 401,不是 bug,是 token 到期了。后来我在 fixture 里加了过期自动刷新。

幂等。同一个 out_trade_no 提交两次,应该返回同一个订单,不是创建两单。这个必须专门写用例,串行跑一百次也跑不出来。

并发。库存 1 件,50 个并发下单,最后卖出两件。这个问题只有并发用例能发现,单条串行用例永远是绿的。

越权。用 A 用户的 token 去请求 B 用户的订单 ID。这个真别省,我见过线上改个 orderId 就能看别人订单的系统。

现在我的 210 条是这么分的

冒烟 30 条。每个核心链路一条,走主干路径。每次 merge request 触发,两分钟出结果,失败了自动在群里 @ 提交人。

图片

回归 150 条。每天凌晨一点跑,企业微信机器人推报告,第二天早上来先看这个。

专项 30 条。并发、幂等、越权、边界值。跑得慢,一周一次。

另外加了个定时巡检,30 条用例,每天早上 9 点跑一次,2 分钟。干什么用的?测试环境的配置被研发随手改过,某天接口突然 404,我们第三天下午才发现。加了巡检之后,当天早上就知道了。

最后说点不好听的

接口测试这件事,技术含量真没那么高,难的是克制。

我见过太多人(包括我自己)用用例数量证明自己的价值,1300 条,好看。但那是给测试自己看的 KPI,不是给质量看的。

如果你刚上手,我的建议是反过来的:先别搭框架,拿 Postman 把核心的 20 个接口手工跑通,每一条都把断言写到 DB 那一层。20 条写透了,比你复制粘贴 500 条强得多。

还有个习惯能救你,就是抓包。Charles 或者 mitmproxy,看真实请求长什么样。别照着接口文档写用例——文档和实现不一致的概率,我自己统计过一个小样本,大概 30%,这不是夸张。

最难受的不是这些技术问题。是你花两周写了一整套框架,文档写得漂漂亮亮,半年后同事跟你说:"跑不过了,我先注释掉了。"

🏷️ 标签: