• 简体中文
  • BDD 风格脚本(Gherkin)

    此特性从 Midscene 1.10 开始支持。

    BDD 相关能力仍处于 Beta 阶段,未来 API 可能发生变化。

    Gherkin 是一种用纯文本描述行为示例的语法,常用于 BDD(Behavior-Driven Development,行为驱动开发)流程。一个 BDD 场景通常包含三类步骤:Given 描述前置条件,When 描述用户操作,Then 描述预期结果。

    举例来说,当需要测试待办事项页面的新增功能时,可以把用例写成下面的 Gherkin 脚本。

    Scenario: 添加待办事项
      Given 待办事项页面已经打开
      When 添加一条名为“买牛奶”的待办事项
      Then 待办事项列表中应该包含“买牛奶”

    较长的 GUI 用例也可以写在同一个 Scenario 中。你可以按业务阶段组织步骤,每个阶段都使用一组 GivenWhenThen

    Scenario: 使用保存的地址下单
      Given 购物车中已有“Midscene Mug”
      When 我打开购物车页面
      Then 购物车中应该显示“Midscene Mug”
      And 小计金额应该可见
    
      Given 结算页面已经打开
      When 我选择已保存的收货地址
      Then 收货地址区域应该显示所选地址
    
      Given 支付区域已经可见
      When 我选择已保存的信用卡并提交订单
      Then 页面应该显示订单确认结果
      And 确认页面应该显示订单号

    这种写法适合一个业务 scenario 自然包含多个 UI 阶段的情况,例如购物车确认、配送地址选择、支付和最终确认。

    在 AI 通过自然语言驱动 GUI 操作的场景中,Gherkin 很适合描述操作用例。它让脚本保留自然语言的可读性,同时提供稳定的步骤结构。这种结构也有助于模型生成更规范的用例。

    Gherkin 的完整语法可以参考官方的 Cucumber Gherkin reference

    支持规则

    Midscene 只支持 Gherkin 的一个子集。这个子集围绕单个场景(Scenario)设计,适合描述一段完整的 GUI 操作流程。

    步骤映射

    • Given:调用 aiAct,用于准备前置状态。
    • When:调用 aiAct,用于执行用户操作。
    • Then:调用 aiAssert,用于验证页面结果。
    • AndBut:沿用前一个主关键字。例如,Then 后面的 And 也会调用 aiAssert

    关键字匹配不区分大小写。因此,ANDandAnd 都可以识别。

    场景限制

    每次只支持一个 Scenario:。如果输入里包含多个 Scenario:,Midscene 会报错。

    你也可以省略 Scenario:,直接写步骤。

    Given 待办事项页面已经打开
    When 我添加一条名为“买牛奶”的待办事项
    Then 待办事项列表中应该包含“买牛奶”

    注意事项

    Midscene 会把每个 Gherkin 步骤拆成一次独立的 aiActaiAssert 调用。每一步都应该写完整,明确说明操作对象、动作和预期结果。

    不要在后续步骤中依赖上一条步骤里的省略信息或模糊指代。比如,不要只写“点击它”或“检查结果”,而应该写清楚要点击的对象和要检查的结果。

    下面的写法无法正确执行。原因是步骤之间的上下文相互隔离,后续步骤无法知道“它”和“结果”分别指什么。

    Given 待办事项页面已经打开
    When 我添加一条名为“买牛奶”的待办事项
    And 点击它
    Then 检查结果

    应该写成下面这样。

    Given 待办事项页面已经打开
    When 我添加一条名为“买牛奶”的待办事项
    And 我点击“买牛奶”这条待办事项
    Then “买牛奶”这条待办事项应该显示为已完成

    暂不支持

    下面这些 Gherkin 特性暂不支持:

    • Feature
    • Background
    • Scenario OutlineScenario Template
    • Examples
    • Rule
    • data tables
    • doc strings
    • 变量替换、占位符展开或模板语法
    • 在同一段输入中包含多个 Scenario:

    Midscene 不会把 Gherkin 扩展成一种脚本语言。它只读取 Scenario 和步骤关键字,再把每个步骤交给 Agent 执行。

    循环、条件、变量替换和批量生成等逻辑,应该在调用 Midscene 之前完成。如果需要复用模板,可以先在项目中实现一个 Gherkin 生成器。生成器输出最终的纯文本 Scenario,再交给 runGherkinScenario 执行。

    在 JavaScript 中使用

    在 JavaScript 或 TypeScript 脚本中,可以直接调用 agent.runGherkinScenario()。它接收一段 Gherkin 文本,并按顺序执行其中的步骤。

    下面的示例使用 Playwright fixture 获取 Agent。

    import { test } from '@midscene/web/playwright';
    
    test('add a todo item', async ({ page, agentForPage }) => {
      await page.goto('http://localhost:3000/todos');
    
      const agent = await agentForPage(page);
      await agent.runGherkinScenario(`
    Scenario: 添加待办事项
      Given 待办事项页面已经打开
      When 我添加一条名为“买牛奶”的待办事项
      Then 待办事项列表中应该包含“买牛奶”
      And 待办事项数量应该为 1
    `);
    });

    第二个参数可以传入运行选项。例如,可以为这次执行提供临时上下文。

    await agent.runGherkinScenario(
      `
    Scenario: 添加待办事项
      Given 待办事项页面已经打开
      When 我添加一条名为“买牛奶”的待办事项
      Then 待办事项列表中应该包含“买牛奶”
    `,
      {
        context: '这是一个待办事项示例应用。请使用页面上的输入框和添加按钮完成操作。',
      },
    );

    在 YAML 中使用

    在 YAML flow 中使用 runGherkinScenario 步骤。它的值应该是一段块字符串,里面放一个 scenario。

    web:
      url: http://localhost:3000/todos
    
    tasks:
      - name: Add a todo item
        flow:
          - runGherkinScenario: |
              Scenario: 添加待办事项
                Given 待办事项页面已经打开
                When 我添加一条名为“买牛奶”的待办事项
                Then 待办事项列表中应该包含“买牛奶”
                And 待办事项数量应该为 1

    YAML 执行时,Midscene 会按步骤运行这个 scenario。GivenWhen 步骤会调用 aiActThen 以及后面这个 And 步骤会调用 aiAssert

    备注

    runGherkinScenario 会关闭场景内部的缓存。也就是说,GivenWhen 映射到 aiAct 后,不会使用 aiAct 的规划缓存。

    这样做是为了让每个 Gherkin 步骤都基于当前页面状态重新解释,避免复用旧步骤带来的误判。