多园区改造测试全景:从登录到业务隔离的 7 大模块验证清单
多园区改造真正难的不是写代码,而是怎么证明它没漏。登录态、菜单、角色、同步链路、业务数据、回归兼容——任何一个模块漏测,都可能在生产里埋雷。
本文把改造测试要覆盖的 7 大模块、3 个优先级、5 条上线前最后检查完整拆开。无论你是第一次做多园区改造,还是已经在做第 N 次,这套清单都能直接复用。
🎧 文章导读
🎵 背景音乐

图1:从登录到业务隔离的 7 大测试模块全景
一、目标与边界
1.1 本轮测试要确认的三件事
多园区改造后,所有跨园区逻辑都要”按当前园区生效”,但不能把 A 园区的数据、角色、设备下发到 B 园区。本轮重点确认:
- 登录用户能看到、能切换的园区范围正确。
- 切换园区后,角色、菜单、人员、业务列表都按当前
park_id生效。 - 钉钉同步、
sys_user_park、pass_user、设备下发状态没有因为多园区改造产生脏数据或跨园区下发。
1.2 不测什么
明确不测的边界,让团队对齐预期:
| 不测项 | 原因 |
|---|---|
| 全量性能压测 | 本轮只做关键列表分页和批量同步的抽样观察 |
| 历史业务字段全覆盖 | 只看多园区相关字段是否影响原有主流程 |
| 自动化测试框架新建 | 本轮以接口 + SQL + 前端手工验证为主 |
没有”测全”的项目,只有”够用 + 关键路径有保障”的项目。多园区改造的测试,第一优先级永远是越权和跨园区下发。
二、测试前准备:环境、账号、SQL 自检
2.1 环境和基础数据
启动 service-gateway、admin-service、through-service,按需再起 property-service、security-service、env-service。dev 环境走网关请求时带 devDebug=1:
1 | http://127.0.0.1:<gateway-port>/gateway/admin/xxx?devDebug=1 |
准备两个有效园区 + 一个租户:
| 标识 | 含义 | 要求 |
|---|---|---|
| PARK_A | 主测园区 A | 有用户、角色、设备/业务数据 |
| PARK_B | 对照园区 B | 有不同用户、角色、设备/业务数据 |
| TENANT_1 | 当前租户 | 两个园区同租户,方便排除租户变量 |
准备测试账号矩阵:
| 用户 | 数据要求 | 用途 |
|---|---|---|
super_admin |
可看全部或管理多个园区 | 验证管理端全量能力 |
admin_a |
只属于 PARK_A | 验证单园区隔离 |
admin_b |
只属于 PARK_B | 验证单园区隔离 |
admin_ab |
同时属于 PARK_A、PARK_B | 验证园区切换 |
normal_a |
PARK_A 普通用户 | 验证无管理权限场景 |
ding_user |
钉钉同步用户 | 验证 sys_user_park 和 pass_user |
准备角色矩阵:
| 角色 | 数据要求 | 用途 |
|---|---|---|
role_a |
sys_role.park_id = PARK_A |
A 园区角色 |
role_b |
sys_role.park_id = PARK_B |
B 园区角色 |
role_manage_ab |
所属园区为 PARK_A,管理园区包含 PARK_B | 验证角色管理园区 |
role_global_or_empty |
如项目存在空园区/通用角色 | 验证兼容历史数据 |
2.2 测试前的 SQL 自检清单
测试前先跑这 4 条 SQL,预期前 3 条返回 0 行:
1 | -- 1. 用户所属园区关系不能重复 |
第 4 条如有历史数据,要先标记出来——后续测试不要混入这些账号,否则测试结果会被脏数据污染。
三、7 大测试模块拆解
A. 登录与当前园区上下文
目的:登录态下的园区上下文必须可信,切换园区不能错位。
| 用例 | 操作 | 预期 |
|---|---|---|
| A1 单园区用户登录 | 用 admin_a 登录并查 /user/info |
当前园区为 PARK_A;园区列表只包含 PARK_A;不出现 PARK_B 的角色、园区名、业务数据 |
| A2 多园区用户登录 | 用 admin_ab 登录 |
园区列表包含 PARK_A、PARK_B;默认园区有明确规则,不能随机跳;当前园区字段、角色列表、菜单列表三者一致 |
| A3 切换园区 | admin_ab 切到 PARK_B,再切回 PARK_A |
切到 PARK_B 后只返回 PARK_B 下生效的角色和数据;切回 PARK_A 后恢复 PARK_A 的角色和数据;刷新页面后当前园区不丢失 |
| A4 非授权园区切换 | admin_a 调用切换接口传 PARK_B;用不存在/已删除的 park_id 再调一次 |
接口失败;当前园区不变;不新增 sys_user_role、sys_user_park、缓存上下文等脏数据 |
A4 是越权拦截的关键用例。如果非授权
parkId没被拦下,会被切园区到其他园区——这是上线后最容易出安全事件的入口。
B. 用户所属园区
| 用例 | 关键校验 |
|---|---|
| B1 用户列表展示所属园区 | userParkIds、userParkName 与权限范围一致;多园区用户的园区名称和 ID 顺序一致;PARK_B-only 用户不会因为无关角色混进 PARK_A 结果 |
| B2 编辑用户所属园区 | 给 normal_a 增加 PARK_B 后 sys_user_park 出现两条有效关系;移除 PARK_B 后软删;重复保存不会产生重复有效行 |
| B3 删除或停用用户 | 停用用户不能登录;相关有效关系不再让该用户进入园区;不误删其他用户的 sys_user_park 或 sys_user_role |
C. 角色管理园区
| 用例 | 关键校验 |
|---|---|
| C1 创建/编辑角色所属园区 | sys_role.park_id = PARK_A;PARK_B 普通管理员不可见或不可操作 |
| C2 配置角色管理园区 | sys_role_park 有唯一有效的 (role_id, PARK_B);重复保存不产生重复行;删除后接口不再返回 PARK_B |
| C3 角色列表字段 | 所属园区和管理园区不混淆;搜索和分页不会破坏园区过滤;软删园区或软删角色不出现在有效结果中 |
D. 用户角色分配
这是最容易出问题的模块。多园区用户的角色关系要按 (user_id, role_id, park_id) 区分,否则切园区时菜单会乱套。
| 用例 | 关键校验 |
|---|---|
| D1 单园区分配角色 | 只新增/更新 (normal_a, role_a, PARK_A);PARK_B 没有被写入同角色关系 |
| D2 同一用户多园区分配同一角色 | sys_user_role 按 user_id + role_id + park_id 区分;切 PARK_A 只加载 PARK_A 的角色,切 PARK_B 只加载 PARK_B 的角色 |
| D3 清空某园区角色 | 对 admin_ab 调用角色保存接口,parkId = PARK_A,角色列表为空——只清空 PARK_A 的角色,PARK_B 不受影响 |
| D4 非授权园区角色分配 | 接口拒绝;不写入 sys_user_role;错误提示可定位到无权限或园区不合法 |
D3 是验证”清空不影响其他园区”的关键。如果代码里写错
DELETE WHERE user_id = ?(不带 park_id),整个用户的所有园区角色都会被清空,这是上线后常见的回归 bug。
E. 园区管理员列表
| 用例 | 关键校验 |
|---|---|
| E1 查询某园区管理员 | PARK_A 只返回 sys_user_role.park_id = PARK_A 的有效用户角色;已删除用户、已删除角色、孤立 user_id 不返回;排序按绑定时间倒序 |
| E2 手机号/用户名展示 | 手机号如有加密,接口返回前端期望的明文或脱敏格式;角色名、园区名和 ID 对得上 |
F. 钉钉同步到用户园区
钉钉同步是”数据进入系统的入口”,错了之后下游所有模块都会脏。
| 用例 | 关键校验 |
|---|---|
| F1 有部门用户同步 | sys_user_park.park_id = PARK_A;sys_user_park.org_id 存公司级组织 ID;重复同步不产生重复有效关系 |
| F2 多部门/跨园区用户同步 | 用户能得到 PARK_A、PARK_B 两个有效园区关系;登录后可切换两个园区;每个园区下角色仍按 sys_user_role.park_id 决定 |
| F3 无法识别园区的钉钉用户 | 不写错误的默认 park_id;不生成空 park_id 的 sys_user_park;日志能说明跳过原因 |
G. sys_user 到 pass_user 同步
这是设备下发的源头。如果 pass_user.park_id 错了,门禁/车行下发就会拿错人员。
| 用例 | 关键校验 |
|---|---|
| G1 新用户同步到 pass_user | 新增 pass_user.park_id = PARK_A;delete_flag = '0';需要下发设备时 dist_sync_status = 'PENDING' |
| G2 已存在 pass_user 更新 | 只更新发生变化的字段;园区变更能同步到 pass_user.park_id;需要重新下发时才标记 PENDING |
| G3 多园区用户 pass_user 策略 | 一人一条时必须有明确主园区;一人多园区时必须每条能区分园区;不允许同一设备下发拿错园区人员 |
| G4 软删用户同步 | pass_user 按项目约定软删或停用;已软删记录不被下发任务重新捞起;findByDistSyncStatus('PENDING') 不返回 delete_flag != '0' 的人员 |
G3 在产品未定义一人多园区下发策略时,要标为待确认,不要强行验收。强行写死策略反而会埋雷。
H. 业务数据园区隔离
每个已改造业务模块至少抽 2 个列表、1 个新增、1 个详情、1 个编辑。优先测经常被首页或大屏使用的接口。

图2:admin/through/property/security/env 各业务的园区隔离验证矩阵
| 用例 | 关键校验 |
|---|---|
| H1 列表隔离 | PARK_A 只返回 A 数据;PARK_B 只返回 B 数据;不传 park_id 时以后端当前园区为准,不让前端伪造越权 |
| H2 新增数据自动带当前园区 | 新增记录的 park_id 等于当前园区;前端传其他 park_id 时,后端按权限规则覆盖或拒绝,不能越权写入 |
| H3 详情/编辑/删除越权 | 在 PARK_A 下拿 PARK_B 数据 ID 调详情 → 不可见或返回无权限;编辑、删除失败;数据库无变化 |
| H4 DEFAULT_PARK_ID 回归 | 重点检查 env、security、through 里历史写死 DEFAULT_PARK_ID 的入口;走新增或同步入口,查数据库实际 park_id;已改造入口不再写死默认园区 |
I. 前端页面联调
前端是用户接触的第一线,错位显示(菜单列表与数据不一致)会直接被业务方发现。
| 用例 | 关键校验 |
|---|---|
| I1 顶部园区切换器 | 切换器显示当前园区;列表自动刷新或提示刷新;刷新后当前园区符合产品约定 |
| I2 用户/角色页面 | 字段展示完整,不错位;下拉园区来源符合接口返回;保存后页面立即反映最新关系 |
| I3 无权限提示 | 前端不展示无权限按钮或页面;后端仍然拒绝越权请求;提示不暴露敏感数据 |
J. 回归测试
| 用例 | 关键校验 |
|---|---|
| J1 原单园区流程 | 操作路径和改造前一致;不因为多园区字段必填导致老流程失败 |
| J2 历史空 park_id 数据 | 产品明确允许的通用数据仍可用;不允许的空园区数据不应出现在普通园区视图;需要清洗的数据单独列清单 |
| J3 分页和搜索 | count 和列表使用同一园区过滤条件;搜索不会绕过园区过滤;排序稳定 |
四、测试优先级
| 优先级 | 模块 | 失败影响 |
|---|---|---|
| 第一优先级 | A、D、G、H3 | 越权或下发错误(绝对不能漏) |
| 第二优先级 | B、C、E、F | 管理端使用和同步准确性 |
| 第三优先级 | I、J | 联调体验和历史兼容 |
如果时间只够半天,最低限度要跑:
admin_a不能切 PARK_B。admin_ab切 PARK_A/PARK_B 后菜单和业务列表变化正确。- 给同一用户分别保存 PARK_A、PARK_B 角色,互不覆盖。
- 清空 PARK_A 角色不影响 PARK_B。
- 钉钉同步用户能写入
sys_user_park。 pass_user没有空park_id,新增或变更用户的下发状态符合预期。- PARK_A 下不能详情、编辑、删除 PARK_B 数据。
五、上线前最后检查 SQL
1 | -- 1. 重复用户园区关系 |
预期:上线前 1、2、3、4 返回 0 行;第 5 条如果有结果,要么补 sys_role_park,要么补 sys_user_park,要么确认这些历史角色关系应清理。
六、经验总结
6.1 三个最容易漏的测试场景
- D3 清空某园区角色:很多团队会测”加”,但不测”清空”。”清空”代码路径通常用
DELETE WHERE user_id = ?,忘记带park_id就会清掉所有园区。 - G3 多园区用户 pass_user 策略:一人一条 vs 一人多园区,下发策略完全不同,但产品常常没有明确定义。
- H4 DEFAULT_PARK_ID 回归:历史代码里写死的
DEFAULT_PARK_ID是改造最大的遗留风险。
6.2 编写测试用例的三个原则
- 操作步骤最小化:每条用例只验证一个意图,混入多个验证点会让失败定位变难。
- 预期可观测:预期要写数据库字段、接口字段、缓存键值,不能写”系统正常运行”。
- 失败用例优先:先写”非授权切换”这种应当失败的用例,再写正常通过的用例——前者一旦通过就证明拦截有效。
6.3 测试记录模板
每轮测试记录建议结构:
1 | ## 测试记录 - YYYY-MM-DD |
七、结语
多园区改造不是”加几个字段”那么简单——它是把整个系统的数据访问维度从”全局”切成”按当前园区”。**测试要验证的不是”能不能跑”,而是”会不会跑串”**。本文的 7 大模块清单 + 3 个优先级 + 上线前 5 条 SQL,能覆盖 90% 的多园区改造回归场景。下次接到多园区改造需求,直接把这份清单贴到测试计划里就行。
多园区改造测试的最高原则:A 园区发生的事,绝不能在 B 园区看到。