ENGINEERING NOTES · 工程笔记

一条 docker compose 拉起整个"假世界":拟真测试环境搭建

先交代背景。我们做多租户微信小程序 SaaS,主工程 Java 21 + Spring Boot + PostgreSQL,85 个迁移文件演进至 V113,250 个测试类、1241 个测试方法。前两篇分别讲了自建的微信开放平台模拟器与设计图渲染服务,单个看都跑得不错,拼在一起就出事:去年十二月我复盘整月的联调记录,跑通一次全流程平均要半天,真正写代码的时间不到三成,其余全耗在"对环境"上。这篇讲我们怎么用一条 docker compose 把后端、模拟微信、渲染服务打包成一个"假世界",以及围着它长出来的日常。

一、背景:最贵的一句话是"我这明明是好的"

跨系统测试的痛不在任何一个系统里,在系统之间。三个系统的版本是乘法关系:后端一个版本、模拟器一个版本、渲染服务一个版本,任何一块落后,现象就不一样。

讲个具体的下午。同事改支付回调的重试逻辑,本地跑是绿的,合到主干后在联调环境变红。两个人对着一屏日志查了四十分钟,最后发现他本地的模拟器还是三月初的版本,那之后回调重发的语义改过一次。他嘟囔的那句"我这明明是好的",是我们去年听得最贵的一句话——贵的不是人,是每个人都对,只有环境不对。

数据库是另一个坑。有人排查进件死循环时往库里手工塞了几条中间态数据,排查完忘了删;第二天另一位同事的用例无辜变红,又搭进去一小时。每人的本机一个版本,测试就成了"薛定谔"的:跑之前,你不知道它是不是好的。

二、拟真环境的组成:一套起全套

思路很简单:把"一个能跑通全流程的世界"本身当成交付物,用 docker compose 编排四个服务:

# docker-compose.yml(脱敏示例)
services:
  db:
    image: postgres:16
    healthcheck: {test: ["CMD-SHELL", "pg_isready -U app"], interval: 3s}
  app:
    build: .                     # 主工程
    depends_on: {db: {condition: service_healthy}}
  mock-wechat:                   # 模拟微信开放平台(FastAPI)
    build: ./mock
  renderer:                      # 截图渲染服务(headless 浏览器)
    build: ./renderer

一条 docker compose up -d,四个服务全起;健康检查保证应用一定等数据库就绪才启动。版本矩阵从乘法变回加法:所有人的"假世界"都从同一份 compose 长出来,端口、时区、初始数据全部一致;镜像构建也纳入 CI,compose 文件一改,镜像跟着重出,谁也没有"老版本"可守。

另一半是"一键重置"。我们把测试数据的出厂设置做成原子操作,脚本按固定顺序执行:拒绝新请求、业务库恢复到种子数据(种子以 SQL 文件纳入版本管理)、模拟器清零状态与已发回调、清理渲染产物;四步全部成功才重新放行流量,任何一步失败整体回滚。核心是"原子"二字:早期版本没有拒绝新请求这步,重置进行到一半有人恰好下了单,又脏了一条数据,从此这步成了铁律。

三、联调的日常:起环境、跑旅程、看日志

开发者的一天收成三件套:

make up        # 起全套环境(冷启约 90 秒)
make journey   # 跑黄金旅程:下单→支付→回调→核销→分账→T+1 对账
make logs      # 聚合看四个服务的日志

黄金旅程沿用前面定下的那条:拨好异常开关,从消费者下单一路跑到双侧对账。以前"跑通全流程"是半天的事——装依赖、起服务、造数据、手工点一遍;现在三件套下来几分钟,中途还能随手重置再来一遍。变化最大的不是快,是心理:快到可以随手跑,旅程就从"上线前才做的仪式"变成写代码时的日常动作。新人入职第一天跟完一页 README 就能独立跑通全流程,这在以前要师傅带三天。组里后来流行一句口头禅:"重置一下试试。"这不是重启玄学——重置后问题消失,说明是脏数据;还在,才值得查代码。以前分不清这两种坏,现在一条命令就能分开。

四、数据与状态的可见性:调试不靠猜

模拟器后来长出一个简陋但好用的管理页。左半屏是状态:每个租户的进件走到哪一步、哪些回调已发出、账单落到哪天;右半屏是异常开关面板,打开的开关标红。

别小看这页。以前排查"回调到底发没发",得 curl 一串查询接口、对着 JSON 数状态;现在扫一眼网页。有次同事盯着满屏日志找"钱为什么没入账",我让他打开管理页——支付成功的回调还躺在"待送达"列表里,delay 开关亮着红,是他上一轮用例忘关了。凌晨的办公室只剩风扇声,五秒钟定位完问题,那种安静里的如释重负,值得为它单独写一个页面。调试的本质是把不可见变可见:环境自己会说话,人就不用猜。

五、进阶:CI 里的拟真

同一套 compose 进 CI,思路是"同一份文件,两份参数":CI 复用这份编排,只覆盖资源与范围——端口全部收进内网不对外暴露;渲染服务吃内存,普通提交的流水线只起 db、app、mock-wechat 三个服务跑核心旅程,渲染相关的全量检查放进夜间任务。

取舍上有过两条弯路。试过 CI 单独维护一套精简编排,两周就漂移了——CI 绿、本地红,又回到老路;也试过每次提交全量起四个服务,流水线时长翻了近一倍,得不偿失。最终落点:文件必须是同一份,差异必须显式写在 CI 的覆盖参数里,谁都能看懂两套环境差在哪。还有个隐性收益:新同事第一次跑 CI 挂了,本地用同一套编排必然能复现,排查起点从"猜差异"变成"看日志"。

六、三句话总结

环境对不齐是跨系统测试的第一成本,解法是把环境本身当交付物,一条 compose 拉起整个"假世界"。重置必须做成原子操作,出厂设置才是真出厂。本地与 CI 用同一份编排、加显式参数覆盖,漂移无处藏身。

技术专栏第二季到此收官——二十篇,都是从真项目里长出来的。下一季见。

运营主体:北京位元跃迁科技有限公司。本文同步发布于本号技术专栏,可搬运至 CSDN/掘金。

本文为位元跃迁原创内容,仅代表编辑观点,不构成经营或投资建议;文中涉及的品牌与案例仅作公开信息分析示例。

LET'S TALK

把方法用进你的生意

如果你正在为门店做数字化规划,欢迎和我们聊聊。位元跃迁是微信支付合作伙伴、微信开放平台第三方平台,提供小程序定制、开发咨询与企业数字化服务。

18601279913

业务咨询 · 项目合作 · 代理商合作

了解位元跃迁的服务 →
位元跃迁业务联系微信二维码
微信咨询