插件上线前我列了份「反向验收清单」:不是问自己"做了什么",而是假设"用户会怎么搞砸"

小助手
小助手 版主圣羽星庭 勋望元宿志愿先锋
社区管理
插件开发 156 浏览 0 回复

发版前夜盯着代码看太久,容易陷入"我都测过了"的幻觉。后来我换了个思路:不写"我完成了什么",而是写"用户/环境/权限会怎么背叛我"。这份清单从四个维度出发,每条都带一个"故意搞破坏"的测试动作,比正向检查更能揪出漏网之鱼。

一、权限:先把自己降级成"最弱的人"

正向思维是"admin 能看到所有菜单",反向思维是"contributor 点进来会不会白屏或更糟——看到不该看的"。

我的破坏测试:新建一个只有 `read` 能力的测试账号,把插件所有 URL 手工敲一遍,包括那些理论上"只该出现在后台菜单里"的页面。

踩过的坑:曾有个设置页用了 `current_user_can('manage_options')` 做菜单显示控制,但页面逻辑里漏了二次校验。结果contributor 直接访问 `wp-admin/admin.php?page=my-plugin` 时,页面渲染了一半才报错,中间那段已经泄露了配置项的 key 名。

现在我的入口文件第一行永远是:

if ( ! current_user_can( 'my_plugin_cap' ) ) {
    wp_die( __( 'Cheatin' uh?' ), 403 );
}

菜单注册和页面回调各验一次,不偷懒。

二、路由:把端点地址改得面目全非

REST 路由注册完,别只测 `wp-json/my-plugin/v1/item` 这种"标准姿势"。

我的破坏测试:

  • 把 namespace 大小写打乱:`my-Plugin/V1/item`
  • 末尾加斜杠:`/item/`
  • 用 `index.php?rest_route=/` 这种非重写模式访问
  • 在 permalink 设为"朴素"的环境下再跑一遍

有个端点我用了正则约束 `[\d]+`,结果用户输入 `01` 时 PHP 8.1 的 preg_match 行为变了,返回 404。后来把约束改成 `[1-9]\d*` 才统一。

清单里固定一项:register_rest_route 的 regex 必须在 `plain` 和 `pretty` 两种 permalink 结构下各测一遍。

三、菜单:把父菜单"抽掉"看子菜单会不会悬空

WordPress 的菜单系统有个隐形依赖:子菜单的 `parent_slug` 必须严格匹配父菜单的 `$menu_slug`。差一个字符不会报错,只是子菜单消失得无影无踪。

我的破坏测试:故意把父菜单的 slug 改一个字母,看后台会不会多出一个"孤儿"子菜单挂在默认位置。更隐蔽的是多站点场景——父菜单只在主站注册,子菜单却在所有站点都尝试挂载。

现在我的菜单注册拆成两个函数,父菜单返回 slug,子菜单必须接收这个返回值,不接受硬编码字符串:

$parent = $this->register_parent_menu();
$this->register_submenu( $parent ); // 传错类型直接 TypeError

四、配置:把数据库里的选项删干净再激活

很多人测"全新安装",其实测的是"卸载后立刻重装"——旧选项可能还残留在 `wp_options` 的 autoload 里。

我的破坏测试:

  1. 激活插件,配置几项设置
  2. 停用并删除插件(不触发卸载钩子)
  3. 手动 `DELETE FROM wp_options WHERE option_name LIKE 'my_plugin_%'`
  4. 重新上传激活,看有没有 `Undefined array key` 或者默认值逻辑崩掉

曾经有个设置项用了 `get_option( 'my_plugin_rate_limit', 60 )`,但代码里另一处直接 `$_options['rate_limit']` 没有兜底,全新安装时这个 key 还不存在,直接报错。

现在的规则:所有配置读取走统一封装,禁止直接 `get_option` 后裸用数组下标。

五、一个快速执行的仪式

我把上面这些破坏测试写成了一个私有 CLI 脚本,发版前跑一遍:

wp eval-file preflight-check.php --allow-root \
  --user=test-contributor \
  --url=http://plain-permalink.test

脚本里用 `wp_set_current_user` 切换身份,用 `add_filter( 'pre_option_permalink_structure', ... )` 临时劫持 permalink 结构,把"人工破坏"自动化。

你们发版前有什么"故意搞破坏"的测试招数?尤其是那种"理论上不会有人这么干"却真实发生过的场景。

评论0
回复 · 0
还没有回复
微信客服 微信客服