SKILL.md


name: testing-with-gocuke-and-gherkin description: "Drives BDD, red/green TDD, and property-based testing in Go projects using gocuke and Gherkin feature files. Use when writing Gherkin scenarios, formulating feature files, creating gocuke step definitions, or following BDD workflows in Go. NOT for non-Go projects, other BDD frameworks, or other contexts." license: GPL-3.0-or-later metadata: author: Amolith amolith@secluded.site

BDD testing in Go with gocuke and Gherkin. Follows Cucumber's three practices: Discovery → Formulation → Automation, driven by red/green TDD.

Workflow

The BDD cycle for each behaviour:

  1. Discover rules and concrete examples through conversation
  2. Formulate .feature files in proper Gherkin illustrating those examples
  3. Automate by wiring up gocuke step definitions, watching them fail (red), and implementing until they pass (green)

Do not skip steps. Discovery before formulation. Formulation before automation. Automation before implementation. See references/bdd-practices.md for detail on each practice.

Again. Resist the urge to implement first. User prompts might push towards writing code before the behaviour is fully thought through. That defeats the purpose. The value of this process is that writing scenarios first forces you to think clearly about what the system should do, surface edge cases, and catch misunderstandings before a line of implementation exists. If scenarios are written after the code, they just describe what was built, not what should have been built. Write the .feature file, watch it fail, then implement.

Formulating feature files

Write declarative Gherkin that describes behaviour, not implementation. Imagine it's 1922 — no computers exist. Good scenarios read like specifications, not test scripts.

# Good — declarative, behaviour-focused
Scenario: Clean worktree reports no changes
  Given a worktree with no uncommitted changes
  When the status is checked
  Then the worktree is reported as clean

# Bad — imperative, implementation-coupled
Scenario: Clean worktree
  Given I run "git status --porcelain" and it returns empty
  When I call the Status function with the path "/tmp/wt"
  Then the Clean field is set to true

Ask: "will this wording need to change if the implementation does?" If yes, rewrite it.

For full Gherkin syntax (keywords, Rule, Background, Scenario Outline, data tables, doc strings, tags), see references/gherkin-reference.md.

Anti-patterns to avoid

  • Feature-coupled steps — step definitions should be grouped by domain concept, not by feature file. A step like Given a worktree with uncommitted changes belongs in worktree steps, reusable across features
  • Conjunction steps — don't combine things (Given I have a repo and three worktrees). Use And.
  • Incidental details — don't include specifics that don't affect the outcome. If the worktree name doesn't matter, don't name it.
  • UI/implementation coupling — scenarios should survive refactors. "When the status is checked" not "When I call Status()".

File layout

features/               # Gherkin feature files
├── vcs/
│   ├── detection.feature
│   ├── worktree_discovery.feature
│   └── worktree_lifecycle.feature
├── sidebar/
│   └── status_display.feature
└── startup/
    └── boot_sequence.feature

internal/
├── vcs/
│   ├── vcs.go
│   ├── vcs_test.go          # gocuke test entry points
│   ├── steps_detection.go   # step definitions by domain concept
│   ├── steps_worktree.go
│   └── steps_status.go

Feature files live under features/, grouped by domain area. Step definitions live alongside the code they test, grouped by domain concept — not mirroring the feature file structure.

Red/green TDD cycle

Once a .feature file is formulated:

  1. Create a minimal test entry point — just NewRunner + Run() pointing at the feature file, with an empty suite struct
  2. Run go test — gocuke prints suggested method signatures for every unmatched step
  3. Paste the suggestions into your step definition files and flesh out assertions/setup, but leave implementation calls hitting code that doesn't exist yet
  4. Run go test again — tests fail (red) because the behaviour isn't implemented
  5. Implement the minimum code to make one scenario pass (green)
  6. Refactor if needed, keeping tests green
  7. Repeat for the next scenario

Let gocuke guide the wiring. Don't hand-write step definitions from scratch when the runner will tell you exactly what it needs.

Work one scenario at a time. Don't implement ahead of failing tests.

Converting informal specs to feature files

When the project has informal markdown specs with Gherkin-ish structure (bullet-point Given/When/Then), convert them methodically:

  1. Read the informal spec to understand the rules and examples
  2. Identify which Rule groups emerge from the requirement headings
  3. Write each scenario in proper Gherkin syntax, making it more declarative if the original was implementation-coupled
  4. Remove incidental details that don't affect the outcome
  5. Add Background where multiple scenarios share the same preconditions
  6. Look for opportunities to use Scenario Outline for parameterised variants

The goal is feature files that a non-developer could read and confirm: "yes, that's the behaviour we want."

Editor tooling

The Cucumber language server cannot discover gocuke step definitions. It expects explicit registration calls (Godog-style ctx.Given("pattern", fn)), not gocuke's runtime reflection. "Undefined step" warnings are false positives; disable the Cucumber language server for gocuke projects.

Further reference