QLExpress 规则单元测试框架:上线前自动跑 1000 条用例,拦截逻辑错误!

运营在后台配了一条规则:orderAmount > 10000 && userLevel == 'VIP' 标记为大额订单。配完觉得没问题,直接上线。半小时后客服被用户打爆——所有 VIP 用户的订单都被拦截了,不管金额大小。排查下来发现是规则里多打了个 >,本来应该是 <。就一个字符,损失了几十万。

规则引擎的优点是灵活——运营可以随时改规则,不用开发介入。但灵活的另一面是危险:没有编译器帮你检查,一个手误就上线了。

今天聊聊怎么给规则加上自动化测试——让 1000 条用例在规则上线前跑一遍,逻辑错误当场拦截。


规则引擎的测试为什么难做

传统代码的测试很成熟:JUnit、Mockito、覆盖率工具,流水线上跑一下,绿了就上线。但规则引擎面前,这套流程用不上。

规则不是 Java 代码。它是运营在后台配的一段表达式字符串,比如:

productPrice * 0.8 > competitorPrice && stockQty < 100

这段东西没有编译期检查。你没法给它写 JUnit,因为在 Java 眼里它只是一个字符串。只有等它被 QLExpress 解析执行的时候,逻辑错误才会暴露——而那时候已经在生产环境了。

所以规则测试的核心挑战就一个:在规则生效之前,用一批预定义的输入和预期输出,验证规则的行为是否符合预期。


思路:把规则测试做成数据驱动

既然规则是表达式字符串,那就用"输入 → 期望输出"的表格来驱动测试:

规则: productPrice * discount > 100 ? "HIGH" : "LOW"

| 用例 | productPrice | discount | 期望结果 |
|------|-------------|----------|----------|
| TC01 | 500         | 0.9      | HIGH     |
| TC02 | 100         | 0.9      | LOW      |
| TC03 | 200         | 0.5      | LOW      |
| TC04 | 1000        | 0.8      | HIGH     |

每条用例就是一行数据:给规则需要的变量赋好值,执行规则,拿结果跟期望值比对。一致就通过,不一致就拦截。

这套思路把测试从"写代码"变成了"填表格"。运营和 QA 可以直接在 Excel 或者后台页面里维护测试用例,不用懂 Java。


框架设计:三个角色搞定一切

整体设计上分三个角色:

用例定义器

测试用例的来源。可以是一个 JSON 文件、Excel 表格、或者数据库表。

{
  "ruleId": "risk_score_v2",
  "rule": "orderAmount * riskFactor > threshold ? 'REJECT' : 'PASS'",
  "cases": [
    {
      "name": "高危大额订单",
      "params": {"orderAmount": 50000, "riskFactor": 0.8, "threshold": 30000},
      "expected": "REJECT"
    },
    {
      "name": "低危小额订单",
      "params": {"orderAmount": 1000, "riskFactor": 0.2, "threshold": 30000},
      "expected": "PASS"
    },
    {
      "name": "边界值测试",
      "params": {"orderAmount": 37500, "riskFactor": 0.8, "threshold": 30000},
      "expected": "PASS"
    }
  ]
}

每一条用例包含三个核心字段:输入参数、期望结果,以及一个可读的用例名称方便排查。

规则执行器

封装 QLExpress 的执行逻辑。接收规则表达式和参数,返回执行结果。

执行流程:
  1. 创建 ExpressRunner 实例
  2. 把 params 里的变量逐个 put 到 context 里
  3. runner.execute(rule, context, ...)
  4. 捕获异常 → 记录失败原因
  5. 返回结果

用例运行器

遍历所有用例,逐条执行,收集结果。

用例运行器:

  加载规则和用例列表 → 逐条执行
    │
    ├─ 执行成功 + 结果匹配 → 通过
    ├─ 执行成功 + 结果不匹配 → 失败(记录期望 vs 实际)
    └─ 执行异常 → 失败(记录异常信息)

  最后输出报告:
    总计: 1000
    通过: 987
    失败: 13
    通过率: 98.7%

用例怎么造:别只测正常流程

用例的质量决定了这套框架的威力。如果用例全是正常输入,那跟没测区别不大。

必须要有的几类用例

边界值:变量的最小值、最大值、临界点。比如 amount > 10000,一定要测 9999.99、10000、10000.01。

空值和 null:规则里引用的变量可能会缺失。如果运营配了规则但某个字段没传,QLExpress 会抛异常还是静默返回 null?这个行为必须测试覆盖。

类型边界:QLExpress 对数值类型比较敏感。amount > 10000 这个规则,如果传进来的是字符串 "10000" 而不是数字,行为是否符合预期?每种类型至少测一条。

组合爆炸:多个条件组合时,用正交法覆盖。比如规则有三个独立条件,每个条件两种取值,不需要测 2³ = 8 条,用正交表 4 条就能覆盖主要组合。

运营改规则时自动生成回归用例

如果运营在后台改了一条规则,可以自动对比新旧规则在同一个用例集上的执行结果。结果不一致的用例,自动标出来提醒运营确认。这样改规则的时候就能看到"改了这行会影响哪些场景"。


CI 集成:上线前的最后一道防线

用例和数据都准备好了,最后一步是把它嵌入发布流程:

规则变更流程:

  运营在后台修改规则 → 点击"提交"
    │
    ├─ 自动触发用例测试
    │    ├─ 全部通过 → 规则保存,进入审核
    │    └─ 有失败 → 拒绝提交,展示失败详情
    │
    ├─ 审核人审批
    │    └─ 通过 → 规则发布到生产
    │
    └─ 发布后监控
         └─ 线上实际命中率 vs 用例预期命中率对比

关键点在第二步——自动化测试是提交的前置条件。用例没全绿,规则就进不了审核流程。这一步在代码层面很简单:提供一个 HTTP 接口或者一个命令行工具,管理后台调用它,返回通过/失败。


实战演示:一个完整的测试框架骨架

核心就三个类,几十行代码:

// 用例定义
class TestCase:
    name: string
    params: Map
    expected: any

// 规则执行器
class RuleExecutor:
    execute(rule, params):
        context = new DefaultContext()
        for each (key, value) in params:
            context.put(key, value)
        return runner.execute(rule, context, null, true, false)

// 用例运行器
class RuleTestRunner:
    run(rule, cases):
        report = new TestReport()
        for each case in cases:
            try:
                actual = executor.execute(rule, case.params)
                if actual.equals(case.expected):
                    report.pass(case)
                else:
                    report.fail(case, case.expected, actual)
            catch Exception e:
                report.error(case, e.message)
        return report

TestReport 最终输出一个结构化的结果,包含总数、通过数、失败数,以及每条失败用例的详细信息。前端可以直接渲染成表格,运营一眼就能看到哪些用例没过、实际结果是什么。


总结

规则引擎的测试,说到底是把"规则"这个运行时才确定逻辑的字符串,重新放回编译期的质量保障体系里。

三个角色——用例定义器管数据、规则执行器管引擎、用例运行器管流程——各司其职,拼起来就是一个完整的规则测试框架。

关键点就一个:用例是规则的"类型检查器"。 编译器给你的代码做的检查,用过用例来给规则做。数据维度覆盖够了——边界值、空值、类型、组合——规则的逻辑错误在上线前就能被拦截。

这套框架落地的成本很低,QLExpress 本身就是轻量级的,整个测试框架几百行代码就能搞定。但收益很大——你省的是一次规则事故的赔偿金。


有用的话转给还在让运营裸配规则直接上线的同事。


标题:QLExpress 规则单元测试框架:上线前自动跑 1000 条用例,拦截逻辑错误!
作者:jiangyi
地址:http://jiangyi.space/articles/2026/06/08/1780754420143.html
公众号:服务端技术精选
    评论
    0 评论
avatar

取消