用户反馈里最经典的一类:“为什么你们测试都过了,我这边 App 一直转圈?”——答案通常是没人测过弱网。这篇文章介绍一套基于 mitmproxy 的弱网模拟方案:不依赖真机、可脚本化、可进 CI。
一、为什么用 mitmproxy 而不是系统级工具
| 方案 | 优点 | 缺点 |
|---|---|---|
| 系统工具(Clumsy/ATC) | 傻瓜式 | 绑死 GUI,没法进 CI,参数难精确 |
| 交换机 QoS | 真实 | 成本高、粒度粗、要机房配合 |
| mitmproxy add-on | 可编程、参数精确、CI 友好 | 只覆盖 TCP 层可控部分,DNS/RTT 要配合 |
核心思路:设备流量经过 mitmproxy 代理,用 add-on 在请求/响应路径上插入可控的延迟、限速、丢包,全部用 YAML 声明场景,脚本按场景启动。
二、弱网场景模型
把"弱网"拆成四个独立维度,每个维度单独可调:
1 | # config/proxy/weaknet_scenarios.yaml |
经验值:flaky(间歇性中断)场景抓到的 bug 数量是稳定弱网的 3 倍以上——用户手机的实际网络就是"时好时坏",而不是"稳定很慢"。
三、add-on 实现核心
1 | # rpa_tools/proxy_manager.py(节选) |
限速不是 time.sleep 一刀切,而是按 chunk 发送:bandwidth_kbps 换算成每 KB 的间隔,响应流式分片释放,这样前端能观察到"转圈越来越长"的真实过程,而不是一开始就等很久。
四、和 UI 自动化联动
弱网不是"代理自己跑",而是给 UI 用例套一层场景:
1 |
|
pytest.ini 里注册 weaknet 标记,CI 的 api 档流水线里加一条 pytest -m weaknet 的 job,每个发版前自动过一遍全部弱网场景。
五、断言什么才算"弱网表现合格"
弱网下的测试重点不是功能能不能完成(那是正常网络的测试职责),而是:
- 有 loading 反馈:任何超过 1s 的操作必须有可见的等待指示;
- 失败有出口:超时/断网必须有重试按钮或明确提示,禁止白屏死等;
- 幂等:网络抖动导致重复提交时,服务端不能创建两条订单——这条必须用接口层断言兜住;
- 恢复即续:网络恢复后,之前"卡住"的页面状态要能自然续上,而不是整页白屏要求重进。
六、小结
弱网测试的落地三件套:场景 YAML 化、add-on 可编程、标记进 CI。工具选型上 mitmproxy 的 Python add-on 生态让"网络条件"变成了和普通测试数据一样可以参数化的东西——这是它比 GUI 工具强的根本原因。