1---
2name: testing-with-gocuke-and-gherkin
3description: "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."
4license: GPL-3.0-or-later
5metadata:
6 author: Amolith <amolith@secluded.site>
7---
8
9BDD testing in Go with gocuke and Gherkin. Follows Cucumber's three practices: Discovery → Formulation → Automation, driven by red/green TDD.
10
11## Workflow
12
13The BDD cycle for each behaviour:
14
151. Discover rules and concrete examples through conversation
162. Formulate `.feature` files in proper Gherkin illustrating those examples
173. Automate by wiring up gocuke step definitions, watching them fail (red), and implementing until they pass (green)
18
19Do not skip steps. Discovery before formulation. Formulation before automation. Automation before implementation. See [references/bdd-practices.md](references/bdd-practices.md) for detail on each practice.
20
21Again. 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.
22
23## Formulating feature files
24
25Write declarative Gherkin that describes _behaviour_, not implementation. Imagine it's 1922 — no computers exist. Good scenarios read like specifications, not test scripts.
26
27```gherkin
28# Good — declarative, behaviour-focused
29Scenario: Clean worktree reports no changes
30 Given a worktree with no uncommitted changes
31 When the status is checked
32 Then the worktree is reported as clean
33
34# Bad — imperative, implementation-coupled
35Scenario: Clean worktree
36 Given I run "git status --porcelain" and it returns empty
37 When I call the Status function with the path "/tmp/wt"
38 Then the Clean field is set to true
39```
40
41Ask: "will this wording need to change if the implementation does?" If yes, rewrite it.
42
43For full Gherkin syntax (keywords, Rule, Background, Scenario Outline, data tables, doc strings, tags), see [references/gherkin-reference.md](references/gherkin-reference.md).
44
45### Anti-patterns to avoid
46
47- **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
48- **Conjunction steps** — don't combine things (`Given I have a repo and three worktrees`). Use `And`.
49- **Incidental details** — don't include specifics that don't affect the outcome. If the worktree name doesn't matter, don't name it.
50- **UI/implementation coupling** — scenarios should survive refactors. "When the status is checked" not "When I call Status()".
51
52## File layout
53
54```
55features/ # Gherkin feature files
56├── vcs/
57│ ├── detection.feature
58│ ├── worktree_discovery.feature
59│ └── worktree_lifecycle.feature
60├── sidebar/
61│ └── status_display.feature
62└── startup/
63 └── boot_sequence.feature
64
65internal/
66├── vcs/
67│ ├── vcs.go
68│ ├── vcs_test.go # gocuke test entry points
69│ ├── steps_detection.go # step definitions by domain concept
70│ ├── steps_worktree.go
71│ └── steps_status.go
72```
73
74Feature 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.
75
76## Red/green TDD cycle
77
78Once a `.feature` file is formulated:
79
801. **Create a minimal test entry point** — just `NewRunner` + `Run()` pointing at the feature file, with an empty suite struct
812. **Run `go test`** — gocuke prints suggested method signatures for every unmatched step
823. **Paste the suggestions** into your step definition files and flesh out assertions/setup, but leave implementation calls hitting code that doesn't exist yet
834. **Run `go test` again** — tests fail (red) because the behaviour isn't implemented
845. **Implement the minimum code** to make one scenario pass (green)
856. **Refactor** if needed, keeping tests green
867. **Repeat** for the next scenario
87
88Let gocuke guide the wiring. Don't hand-write step definitions from scratch when the runner will tell you exactly what it needs.
89
90Work one scenario at a time. Don't implement ahead of failing tests.
91
92## Converting informal specs to feature files
93
94When the project has informal markdown specs with Gherkin-ish structure (bullet-point Given/When/Then), convert them methodically:
95
961. Read the informal spec to understand the rules and examples
972. Identify which `Rule` groups emerge from the requirement headings
983. Write each scenario in proper Gherkin syntax, making it more declarative if the original was implementation-coupled
994. Remove incidental details that don't affect the outcome
1005. Add `Background` where multiple scenarios share the same preconditions
1016. Look for opportunities to use `Scenario Outline` for parameterised variants
102
103The goal is feature files that a non-developer could read and confirm: "yes, that's the behaviour we want."
104
105## Editor tooling
106
107The 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.
108
109## Further reference
110
111- **BDD practices (Discovery, Formulation, Automation)**: See [references/bdd-practices.md](references/bdd-practices.md)
112- **Gherkin syntax**: See [references/gherkin-reference.md](references/gherkin-reference.md)
113- **gocuke API and property-based testing with rapid**: See [references/gocuke-api.md](references/gocuke-api.md)