java-tests-tzatziki

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

BDD Test Generation with Tzatziki

使用 Tzatziki 生成 BDD 测试

Generate valid Cucumber
.feature
files from a user's functional specification, using Tzatziki's step definition library as the source of truth for legal step patterns.
根据用户的功能规范生成有效的 Cucumber
.feature
文件,并以 Tzatziki 的 step definition 库作为合法 step 模式的唯一依据。

Principles

原则

These explain the reasoning behind the workflow — understanding them helps you handle edge cases the workflow doesn't explicitly cover.
  1. Steps come from code, not imagination. Tzatziki provides hundreds of pre-built
    @Given
    /
    @When
    /
    @Then
    patterns in its
    *Steps.java
    files. Inventing step text that doesn't match a real definition produces
    UndefinedStepException
    at runtime. Per-module reference files in
    references/steps-*.md
    contain every legal step pattern — read the relevant ones before writing any scenario.
    ⚠️ Never paraphrase or improvise step keywords. Many step patterns use regex constants like
    COMPARING_WITH
    that expand to a small fixed set of keywords (e.g.,
    ""
    empty,
    " exactly"
    ,
    " at least"
    ,
    " only"
    ). Do not substitute natural-language synonyms such as
    "containing"
    ,
    "including"
    ,
    "matching"
    , or any other word that "sounds right" — if the word does not appear in the
    @Given
    /
    @When
    /
    @Then
    annotation regex, the step will be undefined at runtime. When in doubt, re-read the Java source in
    references/steps-*.md
    rather than guessing.
  2. Verify the environment before writing tests. Run at least one existing Cucumber test in the target module before creating new feature files. This catches missing dependencies, broken bootstrap, or misconfigured runners early — before you've invested effort in writing scenarios that can't execute. If no test exists yet, create the minimal bootstrap first and confirm it discovers at least one scenario.
  3. YAML by default for structured data. Tzatziki scenarios are most readable when request bodies, database fixtures, Kafka payloads, and expected results use
    """yml
    doc strings. Fall back to Gherkin tables for naturally tabular data, or raw JSON only when the contract requires it.
  4. Cover exactly what the user asked for — then help them think about what they missed. Generate scenarios for every functional behavior in the user's specification — not just the happy path. But don't silently add extra scenarios either. Instead, after covering the requested scope, actively identify edge cases and present them to the user as optional additions. To identify edge cases effectively, look at three things: (a) every external service call in the scenario — what happens if it returns an error (4xx, 5xx) or times out? (b) every data collection — what happens if it's empty or contains unexpected values? (c) existing test files in the project that test similar features — they often contain error-handling patterns you can adapt for the new scenario. The user decides which edge cases to include, but your job is to surface them so nothing important is missed.
  5. Reuse what exists. If the project already has a runner, bootstrap class, feature location convention, or glue configuration — reuse them. Creating duplicates causes classpath conflicts and confuses test discovery.
  6. Prefer updating existing scenarios over creating new ones. When a specification adds a new field, header, or assertion to an already-tested behavior (e.g., "add a
    traceId
    header to the message this flow already publishes"), the right approach is almost always to modify the
    Then
    assertion of an existing scenario
    that already exercises that behavior, rather than creating a brand-new scenario that duplicates all the same Given/When setup just to check one additional field. Creating a new scenario is only justified when the behavior itself is genuinely new — a different trigger, a different code path, or a different precondition combination that no existing scenario covers. This matters because test suites grow quickly, and every duplicated scenario is a maintenance burden: when the shared setup changes, every copy must be updated in lockstep or the suite becomes inconsistent.
这些原则解释了工作流背后的推理——理解它们有助于处理工作流未明确涵盖的边缘情况。
  1. 步骤来自代码,而非臆想。 Tzatziki 在其
    *Steps.java
    文件中提供了数百个预构建的
    @Given
    /
    @When
    /
    @Then
    模式。编造与真实定义不匹配的 step 文本,会在运行时产生
    UndefinedStepException
    。各模块的参考文件
    references/steps-*.md
    包含所有合法 step 模式——在编写任何场景之前,先读取相关文件。
    ⚠️ 绝不改写或即兴发挥 step 关键字。 许多 step 模式使用诸如
    COMPARING_WITH
    这样的 regex 常量,它们会展开为一组固定且很小的关键字(例如
    ""
    空、
    " exactly"
    、
    " at least"
    、
    " only"
    )。不要替换为
    "containing"
    、
    "including"
    、
    "matching"
    或其他听起来合理的自然语言同义词——如果某个词未出现在
    @Given
    /
    @When
    /
    @Then
    注解的 regex 中,该 step 在运行时就会处于 undefined 状态。存疑时,应重新阅读
    references/steps-*.md
    中的 Java 源代码,而不是猜测。
  2. 编写测试前验证环境。 至少运行目标模块中的一个现有 Cucumber 测试,再创建新的 feature 文件。这样可以尽早发现依赖缺失、bootstrap 损坏或 runner 配置错误,从而避免在无法执行的场景上投入精力。如果尚不存在测试,先创建最小 bootstrap,并确认它至少发现一个场景。
  3. 结构化数据默认使用 YAML。 当请求正文、数据库 fixture、Kafka payload 和预期结果使用
    """yml
    doc string 时,Tzatziki 场景最易读。对于天然呈表格形式的数据,改用 Gherkin table;仅当契约要求时才使用原始 JSON。
  4. 严格覆盖用户要求的内容——然后帮助用户思考遗漏之处。 为用户规范中的每项功能行为生成场景——而不只是 happy path。但也不要悄悄添加额外场景。覆盖要求范围后,应主动识别边缘情况,并将其作为可选补充展示给用户。要有效识别边缘情况,需要检查以下三个方面:(a) 场景中的每次外部服务调用——服务返回错误(4xx、5xx)或超时时会发生什么?(b) 每个数据集合——集合为空或包含意外值时会发生什么?(c) 项目中测试类似功能的现有测试文件——它们通常包含可供新场景复用的错误处理模式。由用户决定是否纳入这些边缘情况,但你的职责是主动指出它们,避免遗漏重要内容。
  5. 复用已有内容。 如果项目已有 runner、bootstrap class、feature 位置约定或 glue 配置,应直接复用。创建重复项会导致 classpath 冲突并混淆测试发现。
  6. 优先更新现有场景,而不是创建新场景。 当规范为某个已经测试过的行为增加了新字段、请求头或断言(例如“为消息流新增
    traceId
    请求头,而该消息流本身已有测试”)时,正确的做法几乎总是修改现有场景的
    Then
    断言
    ,该场景已经执行了这一行为,而不是创建一个全新的场景,重复所有相同的 Given/When 设置,仅仅为了检查一个额外字段。只有当行为本身确实是新行为时,创建新场景才有充分依据——例如具有不同的触发条件、不同的代码路径,或现有场景未覆盖的不同前置条件组合。这一点很重要,因为测试套件会快速膨胀,而每个重复场景都会带来维护负担:当共享设置发生变化时,每个副本都必须同步更新,否则测试套件将变得不一致。

Workflow

工作流

1. Understand the Specification

1. 理解规范

Analyze the user's input and break it into a checklist of distinct functional behaviors. Each behavior will become one or more scenarios. If anything is ambiguous, ask before proceeding.
While analyzing, classify each behavior as one of:
  • New behavior — a genuinely new trigger, code path, or precondition combination that no existing scenario covers. This requires a new scenario.
  • Additive change — a new field, header, assertion, or output added to an already-tested behavior (e.g., "add a
    traceId
    header to the message this scenario already publishes"). This should be handled by modifying the existing scenario's assertions, not by creating a new scenario. See Principle 6.
Also extract:
  • External dependencies — every API, service, or data source the feature interacts with. Each one is a potential source of edge-case scenarios (errors, timeouts, empty responses).
  • Performance or reliability hints — if the spec mentions performance concerns, large data volumes, or error handling, note them. These signal scenarios the user likely cares about even if they didn't write explicit acceptance tests for them.
  • Implicit error paths — if the spec says "call service X to get Y", the spec is describing the happy path. The failure path (service X returns an error) is an edge case to suggest.
分析用户输入,并将其拆解为不同功能行为的清单。每项行为将对应一个或多个场景。如果存在歧义,应先询问用户。
分析时,将每项行为归为以下类别之一:
  • 新行为——现有场景未涵盖的全新触发条件、代码路径或前置条件组合。这需要创建新场景。
  • 增量变更——为某个已经测试过的行为增加新字段、请求头、断言或输出(例如“为当前场景已发布的消息新增
    traceId
    请求头”)。应修改现有场景的断言,而不是创建新场景。参见原则 6。
同时提取:
  • 外部依赖——该功能交互的每个 API、服务或数据源。每项依赖都可能是边缘场景的来源,例如错误、超时或空响应。
  • 性能或可靠性提示——如果规范提到了性能问题、大数据量或错误处理,应将其记录下来。这些信号表明,即使用户没有明确编写验收测试,他们也很可能重视相应场景。
  • 隐式错误路径——如果规范写的是“调用服务 X 获取 Y”,说明其描述的是 happy path。失败路径,即服务 X 返回错误,属于应提出的边缘情况。

2. Discover the Project

2. 发现项目

Detect the build tool (prefer wrappers:
./mvnw
over
mvn
,
./gradlew
over
gradle
), then:
  1. Always read
    references/steps-core.md
    — core step definitions (ObjectSteps) are used in every Tzatziki project for variables, assertions, and data manipulation.
  2. Detect which
    tzatziki-*
    modules
    the project depends on by inspecting
    pom.xml
    or
    build.gradle
    for dependency declarations. A quick way to extract them:
    bash
    grep -o 'tzatziki-[a-z-]*' pom.xml | sort -u
  3. Read the matching per-module reference(s) based on detected dependencies:
    • HTTP/REST testing →
      references/steps-http.md
    • Spring context →
      references/steps-spring.md
    • JPA/database →
      references/steps-spring-jpa.md
    • Kafka messaging (plain Apache Kafka) →
      references/steps-kafka.md
    • Kafka messaging (Spring Kafka) →
      references/steps-spring-kafka.md
    • MongoDB →
      references/steps-spring-mongodb.md
    • OpenSearch →
      references/steps-opensearch.md
    • Logging assertions →
      references/steps-logback.md
    • MCP/AI testing →
      references/steps-mcp.md
  4. When in doubt between a step pattern inferred from a
    .feature
    example and one read from the Java
    *Steps.java
    source, trust the Java source.
  5. Catalog error-handling patterns from existing
    .feature
    files you encounter during discovery. Note how the project tests HTTP error responses (e.g., mocking 404/500 from external APIs), empty data, cache misses, or retry behavior. You'll use these patterns as templates when suggesting edge cases in Step 5.
检测构建工具(优先使用 wrapper:
./mvnw
而非
mvn
,
./gradlew
而非
gradle
),然后:
  1. 始终读取
    references/steps-core.md
    ——核心 step definition(ObjectSteps)用于每个 Tzatziki 项目中的变量、断言和数据操作。
  2. 检查
    pom.xml
    或
    build.gradle
    中的依赖声明,确定项目依赖了哪些
    tzatziki-*
    模块。快速提取方式如下:
    bash
    grep -o 'tzatziki-[a-z-]*' pom.xml | sort -u
  3. 根据检测到的依赖,读取匹配的模块参考文件:
    • HTTP/REST 测试 →
      references/steps-http.md
    • Spring context →
      references/steps-spring.md
    • JPA/数据库 →
      references/steps-spring-jpa.md
    • Kafka 消息传递(原生 Apache Kafka)→
      references/steps-kafka.md
    • Kafka 消息传递(Spring Kafka)→
      references/steps-spring-kafka.md
    • MongoDB →
      references/steps-spring-mongodb.md
    • OpenSearch →
      references/steps-opensearch.md
    • 日志断言 →
      references/steps-logback.md
    • MCP/AI 测试 →
      references/steps-mcp.md
  4. 如果从
    .feature
    示例推断出的 step 模式与从 Java
    *Steps.java
    源代码读取的模式之间存在疑问,应以 Java 源代码为准。
  5. 从发现过程中遇到的现有
    .feature
    文件中归纳错误处理模式。记录项目测试 HTTP 错误响应的方式,例如模拟外部 API 返回 404/500、处理空数据、缓存未命中或重试行为。第 5 步提出边缘情况时,可将这些模式作为模板。

3. Check the Bootstrap

3. 检查 Bootstrap

Search for the existing test infrastructure:
  • Runner:
    @Suite
    +
    @IncludeEngines("cucumber")
    (JUnit 5) or
    AbstractTestNGCucumberTests
  • Feature location:
    @SelectClasspathResource(...)
    or
    @SelectDirectories(...)
  • Spring context:
    @CucumberContextConfiguration
    +
    @SpringBootTest
    (if Spring is used)
If any piece is missing, plan to create it. Read
references/bootstrap-templates.md
for the JUnit 5 runner and Spring configuration templates.
搜索现有的测试基础设施:
  • Runner:
    @Suite
    +
    @IncludeEngines("cucumber")
    (JUnit 5)或
    AbstractTestNGCucumberTests
  • Feature 位置:
    @SelectClasspathResource(...)
    或
    @SelectDirectories(...)
  • Spring context:
    @CucumberContextConfiguration
    +
    @SpringBootTest
    (使用 Spring 时)
如果缺少任何部分,应计划创建。需要时,读取
references/bootstrap-templates.md
中的 JUnit 5 runner 和 Spring 配置模板。

4. Verify the Environment

4. 验证环境

Run the existing test suite in the target module to confirm it works:
bash
undefined
在目标模块中运行现有测试套件,确认其正常工作:
bash
undefined

Maven

Maven

./mvnw -pl <module> -Dtest=<RunnerClass> test
./mvnw -pl <module> -Dtest=<RunnerClass> test

Gradle

Gradle

./gradlew :<module>:test --tests <RunnerClass>

A passing or functionally-failing run is fine — what matters is that Cucumber discovers and
executes scenarios. `Tests run: 0` means the runner or feature discovery is broken and needs
fixing before you write anything new.
./gradlew :<module>:test --tests <RunnerClass>

测试通过或出现功能断言失败均可——关键是 Cucumber 能够发现并执行场景。`Tests run: 0` 表明 runner 或 feature 发现机制已损坏,必须在编写任何新内容前修复。

5. Propose the Plan

5. 提出计划

⛔ This is a mandatory checkpoint. Do not proceed to Step 6 without the user's explicit approval. Even if the user's specification already includes detailed acceptance tests, present the plan anyway — the user expects to review it, may want to adjust scope, and needs the chance to approve or add edge cases they care about. Skipping this step risks generating the wrong tests and wasting effort.
Output the full plan as regular response text first (never embed a long plan inside the
ask_user
question — the UI truncates it). Include:
  • Files to create or modify
  • A table mapping each requested functional behavior to a scenario — for each row, indicate whether this is a modify (updating an existing scenario) or a new scenario. Use the behavior classification from Step 1 to decide.
  • Any bootstrap work needed
  • Suggested edge cases (clearly marked as optional) — see below for how to identify them
⛔ 这是一个强制检查点。 未获得用户明确批准前,不得进入第 6 步。即使用户规范已包含详细验收测试,也必须先展示计划——用户需要审阅计划,可能希望调整范围,也需要有机会批准计划或添加其关注的边缘情况。跳过此步骤可能导致生成错误的测试并浪费工作。
首先以常规响应文本输出完整计划(切勿在
ask_user
问题中嵌入长计划——UI 会将其截断)。应包括:
  • 要创建或修改的文件
  • 将每项要求的功能行为映射到场景的表格——每一行都应标明是修改现有场景还是创建新场景。使用第 1 步的行为分类作出决定。
  • 所需的 bootstrap 工作
  • 建议的边缘情况(明确标为可选)——识别方法见下文。

Prefer modifying existing scenarios

优先修改现有场景

Before proposing a new scenario, search the project's existing
.feature
files for scenarios that already exercise the same behavior flow (same endpoint, same Kafka topic, same trigger). When you find one, the default action is to modify that scenario — for example, adding a new field to its
Then
assertion table or adding a header check — rather than creating a new scenario with duplicated
Given
/
When
steps. This avoids test bloat and maintenance overhead.
Create a new scenario only when:
  • No existing scenario covers the relevant behavior flow at all
  • The new behavior requires genuinely different preconditions (different data setup, different trigger, different error path) that would make the existing scenario confusing if combined
  • The user explicitly asks for a separate scenario
Example — adding a
traceId
header to an existing emitted message:
  • ❌ Wrong: Create a new scenario "published message includes traceId header" that copies the entire Given/When from the existing message-publication scenario, just to add
    headers: traceId: abc-123
  • ✅ Right: Modify the existing message-publication scenario's
    Then
    block to include
    headers: traceId: abc-123
    alongside its existing assertions
Then use the
ask_user
tool with a short, focused question asking only for the user's decision (e.g. "Does this plan look good, and which optional edge cases would you like to include?"). Do not write any
.feature
file until the user confirms.
在提出新场景之前,搜索项目现有的
.feature
文件,寻找已经执行相同行为流的场景,例如相同 endpoint、相同 Kafka topic 或相同 trigger。找到后,默认操作应是修改该场景,例如在其
Then
断言表中增加字段或增加请求头检查,而不是创建一个重复 Given/When step 的新场景。这样可以避免测试膨胀和维护开销。
仅在以下情况下创建新场景:
  • 现有场景完全没有涵盖相关行为流
  • 新行为确实需要不同的前置条件,例如不同的数据设置、不同的 trigger 或不同的错误路径;若合并到现有场景中会造成混淆
  • 用户明确要求使用独立场景
示例——为现有已发送消息添加
traceId
请求头:
  • ❌ 错误:创建新场景“已发布消息包含 traceId 请求头”,复制现有消息发布场景中的全部 Given/When,仅为了添加
    headers: traceId: abc-123
  • ✅ 正确:修改现有消息发布场景的
    Then
    块,在已有断言旁加入
    headers: traceId: abc-123
随后使用
ask_user
工具,提出一个简短且聚焦的问题,只询问用户的决定,例如“这个计划是否合适,您希望包含哪些可选边缘情况?”。在用户确认前,不要写入任何
.feature
文件。

Identifying edge cases

识别边缘情况

Use the external dependencies, error patterns, and spec hints you gathered in Steps 1 and 2 to build a concrete list of optional edge-case scenarios. Work through these categories:
  1. External service failures — For each external API call in the scenario consider what happens when it returns:
    • A client error (400, 404) — e.g., the resource doesn't exist
    • A server error (500, 502, 503) — e.g., the service is down
    • An empty or unexpected response body
  2. Empty and boundary data — For each data collection involved:
    • What if the collection is empty? (e.g., a super model with no models, a model with no articles, an overridden rule with an empty
      value
      list)
    • What if it contains a single element vs. many?
    • What if values are null or missing?
  3. State and ordering — Cache hit vs. miss, pre-existing vs. fresh data, concurrent modifications, retry after failure (CREATED → TO_RETRY → ERROR).
  4. Patterns from existing tests — In Step 2 you cataloged error-handling patterns from the project's existing
    .feature
    files. Adapt those patterns to the new feature. For example, if existing tests mock a 404 from
    /masterdata/v2/arbo/models/{id}/articles
    and assert "0 kafka messages", suggest the same pattern for any new external API the feature calls.
Present each suggested edge case with a one-line description and mark them as (optional). The user decides which to include.
使用第 1、2 步收集的外部依赖、错误模式和规范提示,构建一份具体的可选边缘场景清单。逐一检查以下类别:
  1. 外部服务故障——针对场景中的每次外部 API 调用,考虑以下情况:
    • 客户端错误(400、404)——例如资源不存在
    • 服务器错误(500、502、503)——例如服务不可用
    • 响应正文为空或与预期不符
  2. 空数据与边界数据——针对涉及的每个数据集合:
    • 如果集合为空会怎样?例如,一个不含任何 model 的 super model、一个不含 article 的 model,或一个
      value
      列表为空的 overridden rule
    • 如果集合包含单个元素而非多个元素会怎样?
    • 如果值为 null 或缺失会怎样?
  3. 状态与顺序——缓存命中与未命中、预先存在的数据与新数据、并发修改,以及失败后重试(CREATED → TO_RETRY → ERROR)。
  4. 现有测试中的模式——第 2 步中归纳了项目现有
    .feature
    文件里的错误处理模式。将这些模式应用到新功能。例如,如果现有测试会模拟
    /masterdata/v2/arbo/models/{id}/articles
    返回 404,并断言“0 kafka messages”,则可对新功能调用的外部 API 使用相同模式。
每项建议的边缘情况均用一行描述,并标记为**(可选)**。由用户决定是否纳入。

6. Implement and Validate

6. 实现并验证

⛔ Mandatory: run tests before responding. After writing or modifying any
.feature
file, you must run the tests and confirm that the output contains zero
"step(s) are undefined"
/
UndefinedStepException
errors before you respond to the user. Do not present a summary table, declare "implementation complete", or ask for feedback until this validation has passed. A visual check of the step text is not sufficient — only the test runner output is authoritative.
  1. Write the
    .feature
    file using exact step patterns from step 2 and matching the existing project's style (scenario naming,
    Background
    usage, tags, data format conventions).
  2. If no feature convention exists, default to
    src/test/resources/features
    with
    @SelectClasspathResource("features")
    .
  3. Run the tests and inspect the output. The test output is the ground truth for step validity — no amount of visual inspection replaces it. Look specifically for these errors:
    • "step(s) are undefined"
      +
      "You can implement these steps"
      — means the step text doesn't match any registered step definition. This is the most common mistake and it must be fixed before the task is considered done. Go back to the per-module
      references/steps-*.md
      files, find the correct pattern, and rewrite the step.
    • UndefinedStepException
      — same root cause, different presentation.
    • ParseError
      — malformed Gherkin syntax.
    • Tests run: 0
      — runner or feature discovery is broken. Accept functional assertion failures (e.g.
      expected 200 but got 404
      ) — they're expected in BDD when the product behavior isn't implemented yet.
  4. Repeat until every requested behavior from step 1 is present and zero undefined-step errors remain in the test output.
⛔ 必须:回复前运行测试。 写入或修改任何
.feature
文件后,必须运行测试,并确认输出中包含零个
"step(s) are undefined"
/
UndefinedStepException
错误,然后才能回复用户。在验证通过之前,不要展示汇总表、宣称“实现已完成”或请求用户反馈。仅靠目视检查 step 文本并不充分——只有测试运行器的输出才具有权威性。
  1. 使用第 2 步中的精确 step 模式编写
    .feature
    文件,并与项目现有风格保持一致,例如场景命名、
    Background
    使用方式、tags 和数据格式约定。
  2. 如果项目不存在 feature 约定,默认使用
    src/test/resources/features
    ,并配合
    @SelectClasspathResource("features")
    。
  3. 运行测试并检查输出。 测试输出是判断 step 是否有效的依据——任何目视检查都无法替代它。重点查找以下错误:
    • "step(s) are undefined"
      +
      "You can implement these steps"
      ——表示 step 文本与任何已注册的 step definition 都不匹配。这是最常见的错误,必须在任务完成前修复。返回各模块的
      references/steps-*.md
      文件,找到正确模式并重写 step。
    • UndefinedStepException
      ——根因相同,但表现形式不同。
    • ParseError
      ——Gherkin 语法错误。
    • Tests run: 0
      ——runner 或 feature 发现机制已损坏。 功能断言失败可以接受,例如
      expected 200 but got 404
      ——当产品行为尚未实现时,这属于 BDD 中预期出现的结果。
  4. 重复上述过程,直到第 1 步中的每项要求行为都已涵盖,并且测试输出中不存在任何 undefined step 错误。

Post-implementation modifications

实现后的修改

When the user requests changes to already-written scenarios (e.g. convert to
Scenario Outline
, add an assertion, merge steps, rename, restructure), the validation requirement still applies:
  1. Apply the requested edits to the
    .feature
    file.
  2. Re-run the tests immediately — even if the change looks trivial. Edits that restructure step text, add new
    Then
    assertions, or reorganize tables frequently introduce subtle syntax mismatches that only the test runner can catch.
  3. If undefined-step errors appear, fix them before responding to the user.
This loop (edit → run → fix) applies to every modification, not just the initial implementation. Never skip the test run, even if the user is asking for a "small" change.
Running a single feature from the CLI: When you need to target one specific feature file or scenario line, use
cucumber.features
as the selector — not
-Dtest=...
or
cucumber.filter.name
. Read
references/cli-execution.md
for the full details, because
cucumber.features
triggers standalone Cucumber execution that bypasses the runner's
@ConfigurationParameter
annotations.
当用户要求修改已经编写的场景,例如转换为
Scenario Outline
、增加断言、合并 step、重命名或重组结构时,验证要求仍然适用:
  1. 应用对
    .feature
    文件的修改。
  2. 立即重新运行测试——即使改动看似很小也不例外。重组 step 文本、增加新的
    Then
    断言或重新组织表格等修改经常会引入只有测试运行器才能发现的细微语法不匹配。
  3. 如果出现 undefined step 错误,必须先修复再回复用户。
此循环(修改 → 运行 → 修复)适用于每一次修改,不仅限于首次实现。即使用户只是要求进行一项“小改动”,也绝不能跳过测试运行。
从 CLI 运行单个 feature: 需要定位到某个特定 feature 文件或场景行时,使用
cucumber.features
作为选择器——不要使用
-Dtest=...
或
cucumber.filter.name
。有关完整说明,请读取
references/cli-execution.md
,因为
cucumber.features
会触发独立的 Cucumber 执行,绕过 runner 的
@ConfigurationParameter
注解。

Success Criteria

成功标准

  • At least one existing test was run and confirmed operational before new scenarios were written.
  • The plan was presented to the user and approved before any
    .feature
    file was written.
  • Generated scenarios cover 100% of the functional behaviors the user explicitly requested.
  • All step text comes from real Tzatziki step definitions (no invented steps). In particular, no natural-language synonyms were substituted where the step regex expects a specific keyword or an empty string (see Principle 1).
  • Tests were run after every
    .feature
    edit (initial implementation and subsequent modifications) and the output contains zero "undefined step" errors.
    This is the definitive validation — if the test output says
    "step(s) are undefined"
    , the task is not done. The agent must never declare implementation complete or present a summary without first running the tests in the same turn.
  • Any required runner or Spring bootstrap files are in place.
  • Tests are discovered and executed with the correct build tool command.
  • Edge-case scenarios were identified, presented to the user, and included only if approved.
  • Any remaining failures are functional assertions, not technical setup problems.
  • 在编写新场景之前,至少运行了一个现有测试并确认其可正常执行。
  • 在写入任何
    .feature
    文件之前,已向用户展示计划并获得批准。
  • 生成的场景覆盖用户明确要求的全部功能行为,覆盖率达到 100%。
  • 所有 step 文本均来自真实的 Tzatziki step definition,没有编造 step。特别是在 step regex 期望特定关键字或空字符串时,未替换为自然语言同义词(参见原则 1)。
  • 每次编辑
    .feature
    后都运行了测试,包括首次实现和后续修改,且输出中包含零个 undefined step 错误。
    这是最终验证标准——如果测试输出显示
    "step(s) are undefined"
    ,任务就尚未完成。Agent 绝不能在未于同一轮中运行测试的情况下宣称实现完成或展示汇总信息。
  • 所需的 runner 或 Spring bootstrap 文件均已就位。
  • 使用正确的构建工具命令发现并执行测试。
  • 已识别边缘情况并展示给用户,且仅在用户批准后纳入。
  • 所有剩余失败均为功能断言失败,而非技术设置问题。

Reference Files

参考文件

Read these when needed — they contain templates and detailed guidance that would clutter the main workflow:
需要时阅读以下文件;它们包含模板和详细说明,如果放入主工作流会造成内容冗余。

Per-Module Step References (read based on detected dependencies)

各模块 Step 参考文件(根据检测到的依赖读取)

  • references/steps-core.md
    — ObjectSteps: variables, assertions, data manipulation, type conversions. Always read this — core steps are used in every Tzatziki project.
  • references/steps-http.md
    — HttpSteps: HTTP mocking, request/response assertions, REST API testing. Read when the project uses
    tzatziki-http
    .
  • references/steps-spring.md
    — SpringSteps: Spring context, properties, bean manipulation. Read when the project uses
    tzatziki-spring
    .
  • references/steps-spring-jpa.md
    — SpringJPASteps: JPA entity management, database fixtures, persistence assertions. Read when the project uses
    tzatziki-spring-jpa
    .
  • references/steps-kafka.md
    — KafkaSteps: plain Apache Kafka topic management, message producing/consuming, async assertions. Read when the project uses
    tzatziki-kafka
    (Spring-free).
  • references/steps-spring-kafka.md
    — SpringKafkaSteps: Spring-specific Kafka additions (listener-wait consumption, interceptor control, embedded broker). Builds on the core
    tzatziki-kafka
    steps. Read when the project uses
    tzatziki-spring-kafka
    .
  • references/steps-spring-mongodb.md
    — SpringMongoSteps: MongoDB collection management, document fixtures, query asse/rtions. Read when the project uses
    tzatziki-spring-mongodb
    .
  • references/steps-opensearch.md
    — OpenSearchSteps: index management, document indexing, search assertions. Read when the project uses
    tzatziki-opensearch
    .
  • references/steps-logback.md
    — LoggerSteps: log assertion, log level management. Read when the project uses
    tzatziki-logback
    .
  • references/steps-mcp.md
    — McpSteps: MCP server testing, tool invocation, AI integration. Read when the project uses
    tzatziki-test-mcp
    .
  • references/steps-jackson3.md
    — Jackson 3 mapper implementation, serialization behavior, and delegate selection. Read when the project uses
    tzatziki-jackson3
    .
  • references/steps-core.md
    ——ObjectSteps:变量、断言、数据操作和类型转换。始终需要读取——每个 Tzatziki 项目都会使用核心 step。
  • references/steps-http.md
    ——HttpSteps:HTTP mocking、请求/响应断言和 REST API 测试。项目使用
    tzatziki-http
    时读取。
  • references/steps-spring.md
    ——SpringSteps:Spring context、properties 和 bean 操作。项目使用
    tzatziki-spring
    时读取。
  • references/steps-spring-jpa.md
    ——SpringJPASteps:JPA 实体管理、数据库 fixture 和持久化断言。项目使用
    tzatziki-spring-jpa
    时读取。
  • references/steps-kafka.md
    ——KafkaSteps:原生 Apache Kafka topic 管理、消息生产和消费、异步断言。项目使用
    tzatziki-kafka
    (非 Spring)时读取。
  • references/steps-spring-kafka.md
    ——SpringKafkaSteps:Spring 专属的 Kafka 扩展功能,包括 listener-wait 消费、interceptor 控制和嵌入式 broker。构建于核心
    tzatziki-kafka
    step 之上。项目使用
    tzatziki-spring-kafka
    时读取。
  • references/steps-spring-mongodb.md
    ——SpringMongoSteps:MongoDB collection 管理、document fixture 和查询断言。项目使用
    tzatziki-spring-mongodb
    时读取。
  • references/steps-opensearch.md
    ——OpenSearchSteps:index 管理、document 索引和搜索断言。项目使用
    tzatziki-opensearch
    时读取。
  • references/steps-logback.md
    ——LoggerSteps:日志断言和日志级别管理。项目使用
    tzatziki-logback
    时读取。
  • references/steps-mcp.md
    ——McpSteps:MCP server 测试、tool 调用和 AI 集成。项目使用
    tzatziki-test-mcp
    时读取。
  • references/steps-jackson3.md
    ——Jackson 3 mapper 实现、序列化行为和 delegate 选择。项目使用
    tzatziki-jackson3
    时读取。

Other References

其他参考文件

  • references/bootstrap-templates.md
    — JUnit 5 runner and Spring
    @CucumberContextConfiguration
    templates. Read when you need to create a new runner or Spring bootstrap class.
  • references/cli-execution.md
    — How to run a single feature or scenario from the CLI using
    cucumber.features
    , including the Maven/Gradle property-mirroring mechanism. Read when you need to target a specific
    .feature
    file instead of running the full suite.
  • references/bootstrap-templates.md
    ——JUnit 5 runner 和 Spring
    @CucumberContextConfiguration
    模板。需要创建新的 runner 或 Spring bootstrap class 时读取。
  • references/cli-execution.md
    ——如何使用
    cucumber.features
    从 CLI 运行单个 feature 或场景,包括 Maven/Gradle 属性映射机制。需要定位到特定
    .feature
    文件而非运行完整测试套件时读取。