groundwork-verify

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

groundwork-verify

groundwork-verify

Generates Cucumber.js step definitions that test the system as a black box through its external interface. Step definitions live in
docs/specs
— a self-contained layer with its own
package.json
, independent of the project's stack.
生成Cucumber.js步骤定义,通过系统的外部接口以黑盒方式测试系统。 步骤定义存储在
docs/specs
目录中——这是一个独立的层,拥有自己的
package.json
,与项目的技术栈无关。

CONSTRAINT — Epistemic perimeter

约束——认知边界

This skill NEVER reads files outside docs/specs/.
No access to src/, app/, lib/, or any application directory.
If information is missing, ASK the user — never infer it from code.
This is non-negotiable. The skill must have exactly the same information as the Gherkin — no more, no less. Reading application code introduces cognitive bias: the skill learns patterns from the implementation (including bugs) and replicates them in step definitions. Tests end up validating the implementation instead of the contract.
The constraint prevents the bias vector — it doesn't matter if the dev knows the code. What matters is that the skill doesn't use it as source of truth.
Clarification: Information provided verbally by the dev (e.g. "the endpoint changed to POST /refunds") is legitimate input. You MAY update
SPEC-INTERFACE.md
with information the dev tells you directly — the constraint forbids reading application files, not listening to the dev. The interview mechanism works the same way: the dev describes the interface, you write it down.
本工具绝不会读取docs/specs/目录以外的文件。
无法访问src/、app/、lib/或任何应用程序目录。
如果信息缺失,询问用户——绝不要从代码中推断。
这一点是不可协商的。本工具拥有的信息必须与Gherkin文件完全一致——不多不少。 读取应用程序代码会引入认知偏差:工具会从实现(包括bug)中学习模式,并在步骤定义中复制这些模式。最终测试验证的是实现而非契约。
该约束可防止偏差影响——开发人员是否了解代码并不重要。重要的是工具不会将代码作为事实来源。
说明:开发人员口头提供的信息(例如“端点已更改为POST /refunds”)是合法输入。你可以将开发人员直接告知的信息更新到
SPEC-INTERFACE.md
中——该约束禁止读取应用程序文件,但不禁止听取开发人员的说明。这与访谈机制的工作方式相同:开发人员描述接口,你将其记录下来。

When to use

适用场景

  • After implementation completes a feature and you need to verify it matches the spec
  • User asks to generate tests from
    .feature
    files
  • User asks "does the code do what we specified?"
  • New scenarios were added via
    /groundwork extend
    and step definitions need updating
  • 功能实现完成后,需要验证其是否符合规格要求时
  • 用户要求从
    .feature
    文件生成测试时
  • 用户询问“代码是否符合我们的规格要求?”时
  • 通过
    /groundwork extend
    添加了新场景,需要更新步骤定义时

When NOT to use

不适用场景

  • User wants to define or design a feature → use groundwork-discovery
  • User wants unit tests or internal code tests — this skill is black-box only
  • No
    .feature
    files exist yet
  • 用户希望定义或设计功能 → 使用groundwork-discovery
  • 用户需要单元测试或内部代码测试——本工具仅支持黑盒测试
  • 尚未存在
    .feature
    文件时

Quick reference

快速参考

CommandPurpose
/groundwork verify <feature>
Generate/update step definitions for one feature
/groundwork verify
Generate/update step definitions for all features
Interface typeToolingAssertions via
rest
/
rest+web
node-fetch
HTTP status, JSON body
cli
child_process.exec
stdout, stderr, exit code
web
/
rest+web
PlaywrightPage elements, navigation
命令用途
/groundwork verify <feature>
为单个功能生成/更新步骤定义
/groundwork verify
为所有功能生成/更新步骤定义
接口类型工具链断言方式
rest
/
rest+web
node-fetch
HTTP状态码、JSON响应体
cli
child_process.exec
标准输出、标准错误、退出码
web
/
rest+web
Playwright页面元素、导航行为

First action

首次操作

Read
docs/specs/CONVENTIONS.md
if it exists. Then read existing step definitions in
docs/specs/step-definitions/
to understand the style already in use.
Do NOT read any file outside
docs/specs/
.

如果
docs/specs/CONVENTIONS.md
存在,请先读取该文件。 然后读取
docs/specs/step-definitions/
中的现有步骤定义,以了解已使用的风格。
绝对不要读取docs/specs/以外的任何文件。

SPEC-INTERFACE.md — Interface contract

SPEC-INTERFACE.md —— 接口契约

SPEC-INTERFACE.md
lives in
docs/specs/
and is the only source from which this skill gets information about the system under test.
It is written by the dev, not inferred from code. This is the critical point: describing the system explicitly breaks implicit bias — the dev reasons about the contract, not the implementation.
SPEC-INTERFACE.md
存储在
docs/specs/
目录中,是本工具获取被测系统信息的唯一来源。
该文件由开发人员编写,而非从代码中推断。这是关键要点:明确描述系统可打破隐性偏差——开发人员是基于契约而非实现进行思考。

Structure

结构

markdown
undefined
markdown
undefined

Interface Contract

接口契约

Type

类型

rest | web | rest+web | cli
rest | web | rest+web | cli

Base URLs

基础URL

Auth

认证方式

type: bearer | cookie | none token_env: TEST_AUTH_TOKEN # env var name, not the value
type: bearer | cookie | none token_env: TEST_AUTH_TOKEN # 环境变量名称,而非值

Endpoint map

端点映射

Format: METHOD /path → expected response (success | error)

格式: METHOD /path → 预期响应(success | error)

POST /auth/login → 200 {token} | 401 GET /users/:id → 200 {user} | 404 POST /orders → 201 {order} | 422
POST /auth/login → 200 {token} | 401 GET /users/:id → 200 {user} | 404 POST /orders → 201 {order} | 422

Web entry points

Web入口点

Format: <feature><path>

格式: <feature> → <路径>

login → /login dashboard → /dashboard checkout → /checkout
login → /login dashboard → /dashboard checkout → /checkout

Notes

说明

Any contextual information useful for tests, not inferable from scenarios

任何对测试有用、无法从场景中推断的上下文信息


The **Endpoint map** section is the most important: it explicitly maps scenarios → interface, forcing the dev to declare the contract instead of letting the skill deduce it from code.

---

**端点映射**部分是最重要的:它显式地将场景映射到接口,迫使开发人员声明契约,而非让工具从代码中推导。

---

Architecture

架构

Prerequisite

前提条件

The system under test exposes a standard external interface. Step definitions never touch internal code — they interact exclusively through:
  • REST/GraphQL — endpoints
  • CLI — command-line process
  • Web — browser UI
被测系统暴露标准的外部接口。步骤定义绝不会触及内部代码——它们仅通过以下方式与系统交互:
  • REST/GraphQL —— 端点
  • CLI —— 命令行进程
  • Web —— 浏览器UI

Fixed toolchain

固定工具链

Cucumber.js for all cases. Playwright added if any feature uses the
web
interface type.
docs/
  specs/
    package.json              ← cucumber.js (+ playwright if needed)
    cucumber.js               ← cucumber config
    CONVENTIONS.md
    SPEC-INTERFACE.md         ← interface contract (only source of system info)
    features/
      <domain>/<feature>.feature
    step-definitions/
      <domain>/<feature>.steps.js
    support/
      hooks.js                ← Before/After setup and teardown
      world.js                ← shared state across steps
    .env.test.example         ← required env vars, no secrets
所有场景均使用Cucumber.js。如果任何功能使用
web
接口类型,则添加Playwright。
docs/
  specs/
    package.json              ← cucumber.js(如需则包含playwright)
    cucumber.js               ← cucumber配置文件
    CONVENTIONS.md
    SPEC-INTERFACE.md         ← 接口契约(系统信息的唯一来源)
    features/
      <领域>/<feature>.feature
    step-definitions/
      <领域>/<feature>.steps.js
    support/
      hooks.js                ← Before/After 初始化与清理
      world.js                ← 步骤间的共享状态
    .env.test.example         ← 必填环境变量,不含敏感信息

Interface → tooling map

接口→工具链映射

Interface typeHTTP clientNotes
rest
node-fetch
JSON request/response assertions
cli
child_process.exec
spawn process, assert stdout/exit code
web
Playwrightheadless browser, behavioural assertions
A single feature can mix
rest
and
web
steps if the interface type is
rest+web
.

接口类型HTTP客户端说明
rest
node-fetch
JSON请求/响应断言
cli
child_process.exec
启动进程,断言标准输出/退出码
web
Playwright无头浏览器,行为断言
如果接口类型为
rest+web
,单个功能可以混合
rest
web
步骤。

Command

命令

/groundwork verify [feature-name]

/groundwork verify [feature-name]

Generate or update step definitions. Without argument, processes all
.feature
files.

生成或更新步骤定义。不带参数时,处理所有
.feature
文件。

Phase 1 — Interface discovery

阶段1 —— 接口发现

SPEC-INTERFACE.md exists?
├── YES → read the file
│         ↓
│    all necessary information present?
│    ├── YES → proceed to Phase 2
│    └── NO → ask only the missing gaps, update the file
└── NO → enter interview mode
          generate SPEC-INTERFACE.md at the end
          proceed to Phase 2
SPEC-INTERFACE.md是否存在?
├── 是 → 读取该文件
│         ↓
│    是否包含所有必要信息?
│    ├── 是 → 进入阶段2
│    └── 否 → 仅询问缺失的信息,更新文件
└── 否 → 进入访谈模式
          最终生成SPEC-INTERFACE.md
          进入阶段2

Interview (only if the file doesn't exist or is incomplete)

访谈(仅当文件不存在或不完整时)

Ask questions in order, one at a time:
  1. "Interface type: REST API, Web UI, or both?"
  2. "Base URL of the system in test environment?"
  3. "How does it authenticate? Bearer token, session cookie, or none?"
  4. "For each scenario in the
    .feature
    , which endpoint or page is involved?"
Question 4 is the core anti-bias mechanism: the dev manually maps scenarios → interface, without the skill looking at code.
按顺序逐个提问:
  1. “接口类型:REST API、Web UI,还是两者兼具?”
  2. “测试环境中系统的基础URL是什么?”
  3. “系统如何进行认证?Bearer令牌、会话Cookie,还是无需认证?”
  4. “对于
    .feature
    文件中的每个场景,涉及哪个端点或页面?”
问题4是核心的反偏差机制:开发人员手动将场景映射到接口,工具不会查看代码。

Incremental update

增量更新

If
SPEC-INTERFACE.md
exists but has gaps (e.g. a new scenario references an unmapped endpoint):
  • Ask only for the missing information
  • Update the file with append, without touching existing sections
  • Explicitly report what was added

如果
SPEC-INTERFACE.md
存在但存在缺失(例如新场景引用了未映射的端点):
  • 仅询问缺失的信息
  • 通过追加方式更新文件,不修改现有章节
  • 明确报告添加的内容

Phase 2 — Gap analysis

阶段2 —— 差距分析

Compare
.feature
files against existing step definitions in
docs/specs/step-definitions/
:
StatusAction
Missing — scenario with no step definitionGenerate
Broken — step definition referencing a changed endpoint or selectorRegenerate
Obsolete — step definition with no matching scenarioReport to user, do not delete
Only generate what is missing or broken. Never rewrite working step definitions.
Report the gap analysis before generating:
Found 3 scenarios without step definitions:
  - auth/login.feature: "login with expired token"
  - payments/checkout.feature: "checkout with empty cart" (new)
  - payments/checkout.feature: "duplicate order submission" (new)
Generating...

.feature
文件与
docs/specs/step-definitions/
中的现有步骤定义进行比较:
状态操作
缺失 —— 场景无对应步骤定义生成步骤定义
损坏 —— 步骤定义引用了已更改的端点或选择器重新生成步骤定义
过时 —— 步骤定义无匹配场景向用户报告,不删除
仅生成缺失或损坏的步骤定义。绝不重写可用的步骤定义。
在生成前报告差距分析结果:
发现3个无对应步骤定义的场景:
  - auth/login.feature: "使用过期令牌登录"
  - payments/checkout.feature: "空购物车结账"(新增)
  - payments/checkout.feature: "重复提交订单"(新增)
正在生成...

Phase 3 — Generate step definitions

阶段3 —— 生成步骤定义

Use information from
SPEC-INTERFACE.md
(base URLs, endpoints, auth type) to generate step definitions. Never look at application code to determine URLs, selectors, or configuration.
REST pattern:
javascript
// Scenario: <scenario name from .feature>
Given('a registered user exists with email {string}', async function(email) {
  // TODO: adjust to your seed/fixture mechanism
  this.user = await createTestUser({ email });
});

When('they attempt login with incorrect credentials', async function() {
  // URL from SPEC-INTERFACE.md endpoint map
  this.response = await fetch(`${process.env.BASE_URL}/auth/login`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email: this.user.email, password: 'wrong' })
  });
});

Then('the operation fails with an authentication error', async function() {
  assert.strictEqual(this.response.status, 401);
});
Web pattern:
javascript
// Scenario: <scenario name from .feature>
Given('a registered user exists', async function() {
  // TODO: adjust to your seed/fixture mechanism
  this.user = await createTestUser();
});

When('they attempt login with incorrect credentials', async function() {
  // Path from SPEC-INTERFACE.md web entry points
  await this.page.goto(`${process.env.WEB_URL}/login`);
  await this.page.fill('[data-testid="login-email"]', this.user.email);
  await this.page.fill('[data-testid="login-password"]', 'wrong');
  await this.page.click('[data-testid="login-submit"]');
});

Then('the operation fails with an authentication error', async function() {
  await expect(this.page.locator('[data-testid="login-error"]')).toBeVisible();
});
Selector naming convention: Use
data-testid="<page>-<element>"
(e.g.
login-email
,
checkout-submit
). Choose names that describe the UI concept from the scenario, not the implementation. These selectors are declared in the step definitions first — the dev adds them to the markup after.
CLI pattern:
javascript
// Scenario: <scenario name from .feature>
When('they run the export command', async function() {
  this.cliOutput = await exec(`node cli.js export --user=${this.user.id}`);
});

Then('the export succeeds', async function() {
  assert.strictEqual(this.cliOutput.exitCode, 0);
});
Rules for all patterns:
  • Add
    // Scenario: <name>
    comment at the top referencing the
    .feature
    origin
  • Use URLs and paths from
    SPEC-INTERFACE.md
    — comment the source (e.g.
    // URL from SPEC-INTERFACE.md endpoint map
    )
  • Mark with
    // TODO:
    anything requiring manual configuration (seed mechanisms, selectors)
  • For
    @pending
    scenarios, generate a stub with
    pending()
    — do not skip silently
  • For
    @out-of-scope
    scenarios, generate nothing

使用
SPEC-INTERFACE.md
中的信息(基础URL、端点、认证类型)生成步骤定义。绝不要查看应用程序代码来确定URL、选择器或配置。
REST模式:
javascript
// Scenario: <来自.feature的场景名称>
Given('a registered user exists with email {string}', async function(email) {
  // TODO: 根据你的数据初始化机制调整
  this.user = await createTestUser({ email });
});

When('they attempt login with incorrect credentials', async function() {
  // URL来自SPEC-INTERFACE.md的端点映射
  this.response = await fetch(`${process.env.BASE_URL}/auth/login`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email: this.user.email, password: 'wrong' })
  });
});

Then('the operation fails with an authentication error', async function() {
  assert.strictEqual(this.response.status, 401);
});
Web模式:
javascript
// Scenario: <来自.feature的场景名称>
Given('a registered user exists', async function() {
  // TODO: 根据你的数据初始化机制调整
  this.user = await createTestUser();
});

When('they attempt login with incorrect credentials', async function() {
  // 路径来自SPEC-INTERFACE.md的Web入口点
  await this.page.goto(`${process.env.WEB_URL}/login`);
  await this.page.fill('[data-testid="login-email"]', this.user.email);
  await this.page.fill('[data-testid="login-password"]', 'wrong');
  await this.page.click('[data-testid="login-submit"]');
});

Then('the operation fails with an authentication error', async function() {
  await expect(this.page.locator('[data-testid="login-error"]')).toBeVisible();
});
选择器命名规范: 使用
data-testid="<页面>-<元素>"
(例如
login-email
checkout-submit
)。选择能够从场景描述UI概念的名称,而非基于实现的名称。这些选择器先在步骤定义中声明——开发人员随后将其添加到标记中。
CLI模式:
javascript
// Scenario: <来自.feature的场景名称>
When('they run the export command', async function() {
  this.cliOutput = await exec(`node cli.js export --user=${this.user.id}`);
});

Then('the export succeeds', async function() {
  assert.strictEqual(this.cliOutput.exitCode, 0);
});
所有模式的规则:
  • 在顶部添加
    // Scenario: <名称>
    注释,引用对应的
    .feature
    来源
  • 使用
    SPEC-INTERFACE.md
    中的URL和路径——添加来源注释(例如
    // URL来自SPEC-INTERFACE.md的端点映射
  • 对需要手动配置的内容(数据初始化机制、选择器)标记
    // TODO:
  • 对于
    @pending
    场景,生成包含
    pending()
    的存根——不要静默跳过
  • 对于
    @out-of-scope
    场景,不生成任何内容

Phase 4 — Setup (first run only)

阶段4 —— 初始化配置(仅首次运行)

If
docs/specs/package.json
does not exist:
  1. Generate
    docs/specs/package.json
    :
json
{
  "name": "specs",
  "private": true,
  "scripts": {
    "test": "cucumber-js",
    "test:tag": "cucumber-js --tags"
  },
  "dependencies": {
    "@cucumber/cucumber": "^10.0.0",
    "node-fetch": "^3.0.0"
  }
}
Add
"@playwright/test": "^1.0.0"
and
"playwright": "^1.0.0"
if any
web
interface type exists.
  1. Generate
    docs/specs/cucumber.js
    :
javascript
module.exports = {
  default: {
    paths: ['features/**/*.feature'],
    require: ['step-definitions/**/*.steps.js', 'support/**/*.js'],
    format: ['progress-bar', 'html:reports/cucumber-report.html'],
    parallel: 2
  }
}
  1. Generate
    docs/specs/support/world.js
    with shared state (page instance for Playwright, auth tokens, last response)
  2. Generate
    docs/specs/support/hooks.js
    with
    Before
    /
    After
    lifecycle hooks for setup and teardown
  3. Generate
    docs/specs/.env.test.example
    based on
    SPEC-INTERFACE.md
    :
BASE_URL=http://localhost:3000
如果
docs/specs/package.json
不存在:
  1. 生成
    docs/specs/package.json
json
{
  "name": "specs",
  "private": true,
  "scripts": {
    "test": "cucumber-js",
    "test:tag": "cucumber-js --tags"
  },
  "dependencies": {
    "@cucumber/cucumber": "^10.0.0",
    "node-fetch": "^3.0.0"
  }
}
如果接口类型包含
web
,添加
"@playwright/test": "^1.0.0"
"playwright": "^1.0.0"
  1. 生成
    docs/specs/cucumber.js
javascript
module.exports = {
  default: {
    paths: ['features/**/*.feature'],
    require: ['step-definitions/**/*.steps.js', 'support/**/*.js'],
    format: ['progress-bar', 'html:reports/cucumber-report.html'],
    parallel: 2
  }
}
  1. 生成
    docs/specs/support/world.js
    ,包含共享状态(Playwright页面实例、认证令牌、最后一次响应)
  2. 生成
    docs/specs/support/hooks.js
    ,包含
    Before
    /
    After
    生命周期钩子用于初始化和清理
  3. 根据
    SPEC-INTERFACE.md
    生成
    docs/specs/.env.test.example
BASE_URL=http://localhost:3000

Add other required env vars from SPEC-INTERFACE.md here

在此添加SPEC-INTERFACE.md中要求的其他环境变量


6. Add to the project root `package.json` (if it exists):
```json
"test:bdd": "cd docs/specs && npm test"
  1. Add
    docs/specs/.env.test
    to
    .gitignore


6. 如果项目根目录的`package.json`存在,添加以下内容:
```json
"test:bdd": "cd docs/specs && npm test"
  1. docs/specs/.env.test
    添加到
    .gitignore

Drift handling

偏差处理

SPEC-INTERFACE.md
can become stale if the API changes without updating the file. The skill cannot detect this automatically — that would require reading application code, violating the constraint.
Mitigation strategy: CI failure is the drift signal.
CI red for 404 / element not found
   → dev updates SPEC-INTERFACE.md
   → /groundwork verify <feature>   (regenerates step definitions)
   → CI green
Drift is detected at runtime, not compile time. This is an acceptable trade-off: the cost of a false negative in CI is much lower than the cost of tests that validate bugs.

如果API发生变化但未更新文件,
SPEC-INTERFACE.md
可能会过时。本工具无法自动检测到这一点——因为这需要读取应用程序代码,违反约束。
缓解策略:CI失败是偏差的信号。
CI因404/元素未找到而失败
   → 开发人员更新SPEC-INTERFACE.md
   → /groundwork verify <feature>   (重新生成步骤定义)
   → CI恢复正常
偏差在运行时而非编译时被检测到。这是可接受的权衡:CI中假阴性的成本远低于验证bug的测试成本。

Output summary

输出摘要

After generation, always report:
Generated:
  docs/specs/step-definitions/auth/login.steps.js        (3 scenarios)
  docs/specs/step-definitions/payments/checkout.steps.js  (2 scenarios)

Stubs (pending):
  docs/specs/step-definitions/auth/login.steps.js        → "login with biometric" (@pending)

Skipped:
  payments/checkout.feature → "guest checkout" (@out-of-scope)

Obsolete (no matching scenario — not deleted):
  docs/specs/step-definitions/auth/register.steps.js     → "register with invite code"

Next steps:
  1. Copy docs/specs/.env.test.example → docs/specs/.env.test and fill in values
  2. Review // TODO: comments in generated files
  3. Add the required selectors (see prompt below)
  4. cd docs/specs && npm install && npm test
生成完成后,始终报告以下内容:
已生成:
  docs/specs/step-definitions/auth/login.steps.js        (3个场景)
  docs/specs/step-definitions/payments/checkout.steps.js  (2个场景)

存根(待实现):
  docs/specs/step-definitions/auth/login.steps.js        → "使用生物特征登录" (@pending)

已跳过:
  payments/checkout.feature → "访客结账" (@out-of-scope)

过时内容(无匹配场景——未删除):
  docs/specs/step-definitions/auth/register.steps.js     → "使用邀请码注册"

后续步骤:
  1. 复制docs/specs/.env.test.example → docs/specs/.env.test并填写值
  2. 查看生成文件中的// TODO:注释
  3. 添加所需的选择器(见下方提示)
  4. cd docs/specs && npm install && npm test

Selector prompt (only for
web
/
rest+web
features)

选择器提示(仅适用于
web
/
rest+web
功能)

After the output summary, if any step definition uses Playwright selectors, generate a ready-to-copy prompt listing every
data-testid
the step definitions expect. The dev pastes this prompt into their coding agent to add the selectors to the markup.
Format:
---
The following data-testid attributes are required by the BDD step definitions.
Add them to the corresponding UI elements in the application code.

Page: /login
  - data-testid="login-email"       → email input field
  - data-testid="login-password"    → password input field
  - data-testid="login-submit"      → submit button
  - data-testid="login-error"       → error message container (visible on auth failure)

Page: /checkout
  - data-testid="checkout-card"     → credit card input
  - data-testid="checkout-submit"   → place order button
  - data-testid="checkout-success"  → order confirmation message
---
Rules for the selector prompt:
  • Group by page (from
    SPEC-INTERFACE.md
    web entry points)
  • Each line: the exact
    data-testid
    value + a short description of the expected element
  • Include selectors for assertions too (error messages, success states, content checks)
  • Only list selectors that appear in the generated step definitions — no extras

输出摘要后,如果任何步骤定义使用了Playwright选择器,生成可直接复制的提示,列出步骤定义所需的所有
data-testid
。开发人员可将此提示粘贴到其编码工具中,以将选择器添加到标记中。
格式:
---
以下data-testid属性是BDD步骤定义所需的。
请将它们添加到应用程序代码中对应的UI元素上。

页面:/login
  - data-testid="login-email"       → 邮箱输入框
  - data-testid="login-password"    → 密码输入框
  - data-testid="login-submit"      → 提交按钮
  - data-testid="login-error"       → 错误消息容器(认证失败时可见)

页面:/checkout
  - data-testid="checkout-card"     → 信用卡输入框
  - data-testid="checkout-submit"   → 下单按钮
  - data-testid="checkout-success"  → 订单确认消息
---
选择器提示规则:
  • 按页面分组(来自SPEC-INTERFACE.md的Web入口点)
  • 每行:精确的
    data-testid
    值 + 对预期元素的简短描述
  • 包含断言所需的选择器(错误消息、成功状态、内容检查)
  • 仅列出生成的步骤定义中出现的选择器——不添加额外内容

Common mistakes

常见错误

MistakeFix
Reading application code (src/, app/, lib/) to determine URLs or configNEVER. Use only
SPEC-INTERFACE.md
. If info is missing, ask the user.
Rewriting working step definitionsAlways run gap analysis first — only generate what is missing or broken
Assuming the interface type without checking
SPEC-INTERFACE.md
Read the file or ask the user — never infer from code
Importing or calling internal project code in step definitionsStep definitions are black-box — interact only through the external interface
Skipping
@pending
scenarios silently
Generate a stub with
pending()
so they show up in test reports
Deleting obsolete step definitions without askingReport obsolete definitions to the user — never delete automatically
Forgetting
// TODO:
markers on config-dependent code
Mark seed mechanisms, selectors, and URLs that need manual adjustment
Inferring endpoints from code when
SPEC-INTERFACE.md
has gaps
Ask the user to update
SPEC-INTERFACE.md
— never fill gaps from code
错误修复方案
读取应用程序代码(src/、app/、lib/)以确定URL或配置绝对不要。仅使用
SPEC-INTERFACE.md
。如果信息缺失,询问用户。
重写可用的步骤定义始终先进行差距分析——仅生成缺失或损坏的内容
未检查
SPEC-INTERFACE.md
就假设接口类型
读取文件或询问用户——绝不要从代码中推断
在步骤定义中导入或调用项目内部代码步骤定义是黑盒——仅通过外部接口交互
静默跳过
@pending
场景
生成包含
pending()
的存根,使其在测试报告中显示
未询问用户就删除过时的步骤定义向用户报告过时的定义——绝不自动删除
忘记对依赖配置的代码标记
// TODO:
标记数据初始化机制、选择器和需要手动调整的URL
SPEC-INTERFACE.md
存在缺失时从代码中推断端点
要求用户更新
SPEC-INTERFACE.md
——绝不要从代码中填补缺失