
测试技术 - 服务端测试总结
一、微服务架构
微服务已成为主流的系统架构,只有对整体架构有了一定了解后,才能更清楚需要测试什么,在哪些地方会存在风险。
下图展示了微服务的全景组成,也很清晰的展示了一条请求的完整链路。各大互联网公司都会在此基础上开发更加定制化的组件。

1.1 服务网关
Shepherd:https://tech.meituan.com/2021/05/20/shepherd-api-gateway.html
API Gateway 层作为外部请求与内部服务间的流量入口,主要负责对外部流量做如下功能:
- 路由分发&负载均衡:将请求路径/api/xxx/xxx 转发到对应的路由,并提供负载均衡能力
- 鉴权/限流/熔断/降级:这些是网关层支持的通用能力,无业务逻辑
- 协议转换:解析 http 请求信息,通过泛化调用到 RPC/Http/函数化服务,最终返回结果。
API 网关是公司的基础层服务,业务 RD 会在此配置接口信息、限流降级等。
1.2 服务治理平台
OCTO:https://tech.meituan.com/2021/03/08/octo-2.0-service-mesh.html
微服务系统数量过于庞大,通常会有一个服务治理平台用于实现微服务的注册与发现,这部分也属于基础层服务。微服务启动时会将地址(IP PORT)注册到治理平台,以便 API 网关发现可用的微服务实例并完成路由。
QA 使用场景:
- 接口自动化实现泛化调用
- 压测性能指标监控
- 测试环境管理
1.3 SpringBoot/存储/中间件
这是业务逻辑的实现,SpringBoot 通常会分为:
- Controller:流量入口,包含参数处理、权限控制、数据转化等
- Biz/Service:实现核心业务逻辑。Service 层会实现因业务域内的数据处理与事务控制,通常涉及与微服务系统、dao 层、LocalCache、分布式缓存、OSS、第三方 API 等众多组件的交互。
- Dao:主要提供数据操作接口
- Cron:定时任务
- Config:常用组件的配置
- Model/Domain:数据实体定义
- Common:通用工具
- Export:接口定义层
测试需要关注的点:https://tech.qimao.com/fu-wu-duan-ce-shi-zhu-yi-dian-pou-xi/
- 核心功能正常,是否与接口文档一致
- 数据流转正确(增->查->改->查->删->查)
- rpc/db/中间件的异常调用(业务 error/幂等校验/超时)
- DB/中间件常见测试点
- redis:缓存时间/缓存穿透/一致性等
- mySQL:事务、分库分表查询、锁、索引
- MQ:消费异常/消息丢失
1.4 CI/CD
"变更管控"也是预防线上故障的一大专项,通常会依托于 devOps 流水线以及各个原子能力。
1.5 日志管理/链路追踪
熟练使用各种运维工具也很有帮助
- ELK 日志平台可以让我们快速定位 bug 或者验证某个功能点(比如很多第三方请求是否参数正确)
- 每周 error 日志巡检有助于发现未反馈的线上问题
- Promethus+Grafana 可以关注业务/机器数据(上线观测、故障排查、压测观察等场景非常有用)
- traceId 在微服务中非常重要,可以根据它生成调用链路,辅助我们更加精准的测试
二、常用的工具/平台
- 抓包工具:Charles/Fiddler
- 泛接口自动化:testNG/pytest/robotFramework
- 精准测试:jacoco
- 流量回放:FTF/jvm-sandbox/mock
- UI 自动化:Selenium/UI-automation
- 监控告警:CAT/Raptor
- 性能/故障:Quake/Rhino/Chaos
- 服务治理:OCTO
- CICD:Jenkins/devops
三、服务端专项
See Detail 资损防控
四、测试关注点
4.1 幂等性
幂等意味着多次执行所产生的影响和一次执行的影响相同,多见于写操作场景。比如对同一笔订单,收到一次支付回调和多次应该是一致的。
技术手段如何保证幂等性?
- 分布式锁
- 乐观锁(冲突概率不高,一旦冲突就报错,让用户决定)
- 版本号机制:select + version (支付退款场景会使用,适用于重复写不多的情况)
- CAS:通过 compare and set 原子操作实现(ABA 不适用)
- 数据库加行锁 表锁
- 数据库加唯一索引
- Redis 实现分布式锁
- 乐观锁(冲突概率不高,一旦冲突就报错,让用户决定)
- 唯一业务单号:例如支付系统就是支付流水号 payNo
如何测试幂等?
1.在需求评审以及技术方案评审阶段,识别出需要实现幂等的接口,check 是否实现。(通常是写接口,比如发券,支付通知,支付提交等等) 2.可以借助 charles、多次调用接口等方式测试,提升效率 3.测试前应梳理出两条链路:第一条是首次执行时候的数据链路;第二条是多次调用的数据链路,check 是否符合预期
4.2 逻辑兼容性
Case1. 改动已有功能前后端交互逻辑,需要考虑新老版本用户是否兼容
章节自动购买逻辑判断
1. 老版本:自动购买状态存储在 user_book 表,当用户没有设置自动购买时,分销商用户默认自动购买,自然量用户不自动购买
2. 新版本:自动购买状态改存在 user_attr 表,兜底逻辑没变
3. 这样的话,老版本用户在 user_attr 表的状态都没有,所以都进入了兜底逻辑,不符合预期
Case 2. 在原有接口做的改动,改动已有字段的判断/取数/写入逻辑:这个时候一定要梳理清楚该字段的数据链路,否则会留坑
- 某次需求增加了对 templatedId 非空的校验,导致部分不需要传该字段的下单场景失败
- 存储在extra字段中device字段的类型(写入时),但是并没有修改读该字段的场景,导致读取的device_id都是0,订单归属异常
Case 3. 如果活动生效时间不是上线时间,需要在真实生效时间观察:例如 1 月 1 日晚 20 点上线了新代码,但是活动是在 1 月 5 日早 10 点生效,那么需要在这两个时间都留意线上监控情况
Case4. 测试代码兼容性
五、熟悉代码
"代码变更"是线上故障的主要归因,也是服务端 QA 关注重点,因此有必要投入时间熟悉核心功能的代码实现,掌握梳理调用链路。虽然前期来看这是一件 ROI 较低的事情,但是长期来看很有帮助:
并没有想象中花费时间:
- 首先,业务真正核心的接口不多,并且复杂需求大多围绕核心接口做功能扩展或者改造(以支付系统为例,80%的需求都集中在"预支付"、"提交支付"、"退款"这几个接口上)。所以从梳理成本上看,是属于前期投入较高,后面会越来越轻松,如果已有梳理好的文档更是事半功倍。 PS:核心接口一般是 C 端调用的 HTTP 请求,按调用量排序取 TopN。
- 并不需要记住每一行代码,重点关注"系统间&第三方 API 调用"、"数据&缓存读取/写入"以及一些特殊实现。
测试工具在懂代码的 QA 手中更有用
以精准测试为例,虽然许多大厂已经提供了功能完善的工具以及使用手册,但是业务落地时的效果"参差不齐",我认为主要是因为工具只能给出辅助客观的数据,关键还是 QA 工程师自身的能力对这些数据做出判断与响应。这通常是要求具备基础的代码能力和业务代码的熟悉。
许多测试专项本质上就是代码梳理:
我们开展过很多测试专项(强弱依赖治理、监控告警治理等等),这些专项通常的达成路径是工具组 QA 生成现状数据 -> 业务 QA 推动 RD 去 check 补充 -> 业务 QA 收集汇总,推动 RD 改进 -> 持续收集数据,查看对应专项的北极星指标。在实际的落地过程中,会有几个问题:
- 如果对代码没有了解,业务 QA 无法判断生成数据和 RD 确认数据的准确性和效果
- 过于依赖 RD,业务 QA 很容易成为工具人,两头懵
从看懂代码到写代码:
QA 在完成业务测试之余,通常还会做一些平台开发的工作,通常会使用与业务相同的技术栈,多学习 RD 代码也对自己写代码很有帮助。