Skill Improvements: - BDD Testing Skill: Enhanced step templates, debugging guides, and patterns - Gitea Client Skill: Added wiki management, issue tracking, and workflow monitoring - Product Owner Assistant: Improved user story workflow and documentation - Commit Message Skill: Better gitmoji integration and issue referencing - Changelog Manager: Enhanced change tracking and documentation - Skill Creator: Improved skill generation templates and validation - Swagger Documentation: Updated OpenAPI integration guides Key Features: - BDD best practices documentation - Gitea API client with wiki support - User story implementation workflow - Git commit message standardization - Skill development patterns - OpenAPI/Swagger documentation generation Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
13 KiB
name, description, license, metadata
| name | description | license | metadata | ||||||
|---|---|---|---|---|---|---|---|---|---|
| bdd-testing | Behavior-Driven Development testing for dance-lessons-coach using Godog. Use when creating or running BDD tests, implementing new features with BDD, or validating API endpoints through Gherkin scenarios. | MIT |
|
BDD Testing for dance-lessons-coach
Behavior-Driven Development testing framework using Godog for the dance-lessons-coach project. This skill provides comprehensive guidance for creating, running, and maintaining BDD tests that validate API endpoints and system behavior.
Key Concepts
Black Box Testing Principles
- External API Only: Tests interact only through public HTTP endpoints
- No Internal Access: No direct access to database, services, or internal components
- Real HTTP Requests: Actual network calls to verify system behavior
- Isolation: Each scenario runs with fresh client instances
Hybrid In-Process Testing
- Real Server Code: Uses actual server implementation running in-test process
- Fixed Port: Test server runs on port 9191
- No External Processes: Avoids complex process management
- Graceful Shutdown: Proper server lifecycle management
Commands
Run BDD Tests
go test ./features/...
Runs all BDD tests in the features directory using Godog test runner.
Arguments:
- None (uses standard Go test infrastructure)
Validate BDD Tests
./scripts/run-bdd-tests.sh
Validates BDD tests and fails if any undefined, pending, or skipped steps are found.
Arguments:
- None
Create New Feature
# Create new feature file
touch features/<feature_name>.feature
# Add Gherkin scenarios
# Implement step definitions in pkg/bdd/steps/
Arguments:
feature_name- Name of the feature (e.g., "greet", "health")
Workflows
Implementing a New BDD Feature
- Create Feature File: Define scenarios in Gherkin syntax
- Implement Steps: Add step definitions following Godog's exact patterns
- Run Tests: Execute and debug scenarios
- Validate: Ensure no undefined/pending steps
- Document: Add feature documentation
Debugging BDD Tests
- Check Step Patterns: Ensure steps match Godog's exact regex patterns
- Verify Server: Confirm test server is running on port 9191
- Inspect Responses: Check actual vs expected API responses
- Review Logs: Examine test output for undefined steps
- Validate JSON: Ensure proper JSON escaping in feature files
Usage Examples
Creating a Greet Feature
# features/greet.feature
Feature: Greet Service
The greet service should return appropriate greetings
Scenario: Default greeting
Given the server is running
When I request the default greeting
Then the response should be "{\"message\":\"Hello world!\"}"
Scenario: Personalized greeting
Given the server is running
When I request a greeting for "John"
Then the response should be "{\"message\":\"Hello John!\"}"
Creating a Health Feature
# features/health.feature
Feature: Health Endpoint
The health endpoint should indicate server status
Scenario: Health check returns healthy status
Given the server is running
When I request the health endpoint
Then the response should be "{\"status\":\"healthy\"}"
Implementing Step Definitions
// pkg/bdd/steps/steps.go
func (sc *StepContext) theServerIsRunning() error {
// Actually verify the server is running by checking the readiness endpoint
return sc.client.Request("GET", "/api/ready", nil)
}
func (sc *StepContext) iRequestAGreetingFor(name string) error {
return sc.client.Request("GET", fmt.Sprintf("/api/v1/greet/%s", name), nil)
}
func (sc *StepContext) iRequestTheDefaultGreeting() error {
return sc.client.Request("GET", "/api/v1/greet/", nil)
}
func (sc *StepContext) iRequestTheHealthEndpoint() error {
return sc.client.Request("GET", "/api/health", nil)
}
func (sc *StepContext) theResponseShouldBe(arg1, arg2 string) error {
// The regex captures the full JSON from the feature file, including quotes
// We need to extract just the key and value without the surrounding quotes and backslashes
// Remove the surrounding quotes and backslashes
cleanArg1 := strings.Trim(arg1, `"\`)
cleanArg2 := strings.Trim(arg2, `"\`)
// Build the expected JSON string
expected := fmt.Sprintf(`{"%s":"%s"}`, cleanArg1, cleanArg2)
return sc.client.ExpectResponseBody(expected)
}
Registering Steps
// pkg/bdd/steps/steps.go
func InitializeAllSteps(ctx *godog.ScenarioContext, client *testserver.Client) {
sc := NewStepContext(client)
// Use Godog's EXACT regex patterns and parameter names
ctx.Step(`^I request a greeting for "([^"]*)"$`, sc.iRequestAGreetingFor)
ctx.Step(`^I request the default greeting$`, sc.iRequestTheDefaultGreeting)
ctx.Step(`^I request the health endpoint$`, sc.iRequestTheHealthEndpoint)
ctx.Step(`^the response should be "{\"([^"]*)\":\"([^"]*)"}"$`, sc.theResponseShouldBe)
ctx.Step(`^the server is running$`, sc.theServerIsRunning)
}
Gotchas
Step Pattern Matching
- Use Godog's Exact Patterns: Step regex must match Godog's suggestions precisely
- Use Exact Parameter Names: Godog expects
arg1, arg2, not descriptive names - Avoid Undefined Warnings: Even small deviations cause "undefined step" warnings
- Test Patterns First: Use
godog.ErrPendingto verify patterns work before implementing logic - Don't Over-Optimize Regex: Use the patterns Godog provides, even if they seem verbose
Critical Requirements from Validated Implementation
-
Godog has very specific requirements for step pattern matching:
- Use the exact regex pattern that Godog suggests in error messages
- Use the exact parameter names that Godog suggests (
arg1, arg2, etc.) - Match the feature file syntax exactly including quotes and JSON formatting
-
The "undefined" warnings are not a Godog bug - they occur when step definitions don't match Godog's expected patterns exactly:
- Using different regex patterns than what Godog suggests
- Using descriptive parameter names instead of
arg1, arg2 - Not escaping quotes properly in JSON patterns
- Trying to be "clever" with regex optimization
-
Solution: Always use the exact pattern and parameter names that Godog suggests in its error messages.
JSON Escaping
- Feature Files: Use double backslashes for quotes:
"{\\"message\\":\\"Hello\\"}" - Step Implementation: Trim surrounding quotes and backslashes from captured groups
- Response Validation: Trim trailing newlines from JSON responses
Server Verification
- Actual HTTP Requests:
theServerIsRunningmust make real HTTP call to/api/ready - No Mocking: Black box testing requires real server verification
- Port Conflicts: Test server runs on fixed port 9191
Context Handling
- ScenarioContext vs Context: Steps receive
*godog.ScenarioContext, notcontext.Context - Client Access: Store client in StepContext struct for step access
- Fresh Instances: Each scenario gets new client instance
Best Practices
Step Definition Patterns
// ✅ DO: Use Godog's exact regex patterns and parameter names
ctx.Step(`^I request a greeting for "([^"]*)"$`, sc.iRequestAGreetingFor)
ctx.Step(`^the response should be "{\"([^"]*)\":\"([^"]*)"}"$`, sc.theResponseShouldBe)
// ❌ DON'T: Use different parameter names or patterns
ctx.Step(`^I request greeting "(.*)"$`, sc.iRequestAGreetingFor) // Wrong pattern
ctx.Step(`^the response should be "{\"message\":\"([^"]*)"}"$`, sc.theResponseShouldBe) // Wrong pattern
Validated Step Definition Strategy
- First eliminate "undefined" warnings by using Godog's exact suggested patterns
- Return
godog.ErrPendinginitially to confirm pattern matching works - Then implement actual validation logic
- One pattern per step type - Use generic patterns to cover similar steps
Response Validation
// ✅ DO: Trim newlines and properly unescape JSON
func (c *Client) ExpectResponseBody(expected string) error {
actual := strings.TrimSuffix(string(c.lastBody), "\n")
if actual != expected {
return fmt.Errorf("expected %q, got %q", expected, actual)
}
return nil
}
// ❌ DON'T: Assume exact string matching without cleanup
func (c *Client) ExpectResponseBody(expected string) error {
if string(c.lastBody) != expected { // May fail due to newlines
return fmt.Errorf("mismatch")
}
}
Test Server Management
// ✅ DO: Use hybrid in-process testing
func (s *Server) Start() error {
// Start real server in same process
go func() {
if err := s.httpServer.ListenAndServe(); err != nil {
log.Error().Err(err).Msg("Test server failed")
}
}()
return s.waitForServerReady()
}
// ❌ DON'T: Use external process management
func startServer() {
// Avoid: cmd := exec.Command("go", "run", "./cmd/server")
}
Response Validation
// ✅ DO: Trim newlines and properly unescape JSON
func (c *Client) ExpectResponseBody(expected string) error {
actual := strings.TrimSuffix(string(c.lastBody), "\n")
if actual != expected {
return fmt.Errorf("expected %q, got %q", expected, actual)
}
return nil
}
// ❌ DON'T: Assume exact string matching without cleanup
func (c *Client) ExpectResponseBody(expected string) error {
if string(c.lastBody) != expected { // May fail due to newlines
return fmt.Errorf("mismatch")
}
}
Progressive Disclosure
Core Instructions (SKILL.md)
- BDD testing fundamentals
- Common workflows and patterns
- Gotchas and best practices
- Basic troubleshooting
Detailed Reference (references/)
- GODOG_PATTERNS.md: Advanced step pattern examples
- TEST_SERVER.md: Test server implementation details
- DEBUGGING.md: Advanced debugging techniques
- EXAMPLES.md: Complete feature examples
Scripts (scripts/)
- run-bdd-tests.sh: Test validation and execution
- debug-steps.sh: Step pattern debugging
- generate-stubs.sh: Step definition stub generation
Validation
Test Validation Script
# scripts/run-bdd-tests.sh
#!/bin/bash
set -e
echo "Running BDD tests..."
go test ./features/... -v
# Fail if any undefined/pending/skipped steps
echo "Validating test results..."
if go test ./features/... 2>&1 | grep -q "undefined\|pending\|skipped"; then
echo "ERROR: Found undefined, pending, or skipped steps"
exit 1
fi
echo "✓ All BDD tests passed with no undefined steps"
Common Validation Issues
| Issue | Cause | Solution |
|---|---|---|
| Undefined steps | Step pattern doesn't match Godog's exact regex | Use Godog's suggested pattern |
| JSON mismatch | Trailing newlines or improper escaping | Trim newlines, properly unescape JSON |
| Server not running | Test server failed to start | Check port 9191, verify server logs |
| Context errors | Wrong context type passed to steps | Use *godog.ScenarioContext, not context.Context |
References
Troubleshooting
"Undefined Step" Warnings
Symptoms: Tests pass but show "undefined step" warnings
Cause: Step regex doesn't match Godog's exact pattern suggestions
Solution:
- Run
godog --format=progressto see suggested patterns - Update step registration to use exact patterns
- Ensure function names match step descriptions
JSON Comparison Failures
Symptoms: Response validation fails despite correct JSON
Cause: Trailing newlines or improper escaping in feature files
Solution:
- Trim newlines:
strings.TrimSuffix(response, "\n") - Properly escape JSON in feature files:
"{\\"key\\":\\"value\\"}" - Trim quotes in step implementation:
strings.Trim(arg,"`)`
Server Connection Errors
Symptoms: "connection refused" or server not responding
Cause: Test server not running or port conflict
Solution:
- Verify server on port 9191:
curl http://localhost:9191/api/ready - Check server logs for startup errors
- Ensure no other process using port 9191
Context Type Mismatches
Symptoms: Compilation errors about context types
Cause: Passing wrong context type to step functions
Solution:
- Store
*godog.ScenarioContextin StepContext - Use stored context for step registration
- Access client through StepContext struct
Assets
- feature-template.feature: Gherkin feature file template
- step-template.go: Go step definition template
- test-server-template.go: Test server implementation template
- validation-script.sh: Test validation script template