Feature File Organization
Organize Gherkin feature files into a maintainable, scalable structure for Terraform module development. This skill focuses on file organization, scenario grouping, and step definition patterns - complementing the gherkin-scenarios skill which covers syntax.
When to Use This Skill
- •User asks to "organize features", "structure feature files", "split large features"
- •Feature files become too large (>200 lines or >10 scenarios)
- •Scenarios are duplicated across multiple feature files
- •Feature files are hard to navigate or understand
- •Starting a new Terraform module with multiple capabilities
- •Refactoring existing feature files for better maintainability
- •Creating a consistent pattern across team projects
Directory Structure
Standard Layout
For Terraform modules:
docs/features/
├── README.md # Feature index and overview
├── core-functionality.feature # Primary module capability
├── security-configuration.feature # Security-related scenarios
├── networking-integration.feature # Network-related scenarios
└── advanced-features/ # Complex or optional features
├── auto-scaling.feature
├── service-connect.feature
└── observability.feature
Location
Always use: docs/features/ directory (platform-independent)
Not: .github/features/ (platform-specific, legacy)
File Extension: .feature (required for Gherkin parsers)
File Naming
Pattern: domain-concept.feature
Examples:
✅ Good: - ecs-service-creation.feature - load-balancer-integration.feature - auto-scaling-policies.feature - security-group-rules.feature - cloudwatch-logging.feature ❌ Bad: - test.feature (not descriptive) - ECS_Service.feature (use kebab-case) - service-creation-with-auto-scaling-and-load-balancer.feature (too long) - features.feature (too generic)
Grouping Principles
One Feature = One Domain Concept
Rule: Each feature file should focus on ONE major domain object or capability.
For Terraform modules, group by:
- •Core resources (primary infrastructure)
- •Integration points (load balancers, DNS, service mesh)
- •Security (IAM, security groups, encryption)
- •Observability (logging, monitoring, tracing)
- •Scaling (auto-scaling, capacity planning)
- •Networking (VPC integration, routing, DNS)
Example Structure for ECS Module:
docs/features/ ├── ecs-service-creation.feature # Core: Creating the service ├── load-balancer-integration.feature # Integration: ALB/NLB ├── security-configuration.feature # Security: IAM roles, security groups ├── auto-scaling-policies.feature # Scaling: Auto-scaling setup ├── cloudwatch-logging.feature # Observability: Logs and metrics └── service-connect.feature # Advanced: Service mesh
Scenario Count Per Feature
Target: 5-15 scenarios per feature file
If you have:
- •<5 scenarios: Consider merging with related feature
- •>15 scenarios: Split into more focused features
Too many scenarios example:
Feature: Complete ECS Configuration # 30+ scenarios covering everything # This should be split!
Better organization:
ecs-service-creation.feature # 8 scenarios load-balancer-integration.feature # 6 scenarios auto-scaling-policies.feature # 7 scenarios
Background vs Feature Splitting
Use Background when:
- •Setup is identical for all scenarios in the feature
- •3+ scenarios share the same Given steps
Split into separate features when:
- •Different backgrounds are needed
- •Scenarios test different capabilities
- •Natural domain boundaries exist
Example - Keep Together (shared background):
Feature: Auto-scaling Policies
Background:
Given an ECS service with 2 running tasks
And CloudWatch metrics are enabled
Scenario: CPU-based scaling
Scenario: Memory-based scaling
Scenario: Request count scaling
# All share the same background
Example - Split Apart (different contexts):
# ecs-service-creation.feature
Feature: ECS Service Creation
Background:
Given a VPC and subnets
And an ECS cluster
# Scenarios about creating services
# load-balancer-integration.feature
Feature: Load Balancer Integration
Background:
Given an existing ECS service
And a load balancer
# Scenarios about LB integration
Avoiding Duplication
Pattern 1: Parameterized Scenarios
❌ Duplicate Scenarios:
Scenario: Service with 256 CPU and 512 memory Given task definition with CPU 256 and memory 512 When I create the service Then it should be created successfully Scenario: Service with 512 CPU and 1024 memory Given task definition with CPU 512 and memory 1024 When I create the service Then it should be created successfully # 10+ more similar scenarios...
✅ Scenario Outline:
Scenario Outline: Service with various CPU/memory configurations
Given task definition with CPU <cpu> and memory <memory>
When I create the service
Then it should be created successfully
Examples: Valid Fargate configurations
| cpu | memory |
| 256 | 512 |
| 512 | 1024 |
| 1024 | 2048 |
| 2048 | 4096 |
Pattern 2: Reusable Step Definitions
❌ Similar but separate steps:
Given I navigate to the service creation page Given I open the service configuration screen Given I go to the new service form
✅ Generic step with parameter:
Given I navigate to the "{page}" page
Implementation Note: The step definition handles different pages:
@given('I navigate to the "{page}" page')
def navigate_to_page(page):
page_factory.open(page)
Pattern 3: Abstract Helper Steps
❌ Over-specific scenarios:
Scenario: Create service with CloudWatch logs
Given a log group "/ecs/production/app"
And log stream prefix "app"
And retention period 7 days
And log driver awslogs with region us-east-1
And log options {"awslogs-stream-prefix": "app"}
When I create the service
Then logs should be sent to CloudWatch
✅ Abstract scenario with implementation details hidden:
Scenario: Create service with CloudWatch logs Given CloudWatch logging is configured When I create the service Then container logs should be sent to CloudWatch And logs should be retained according to policy
Why better:
- •Scenario focuses on behavior, not implementation
- •Implementation details handled in step definitions
- •Easier to maintain when AWS API changes
- •More readable for non-technical stakeholders
File Organization Patterns
Pattern A: Flat Structure (Simple Modules)
When to use: Modules with <5 major capabilities
docs/features/ ├── README.md ├── core-functionality.feature ├── security-config.feature ├── networking.feature └── observability.feature
Example: S3 Bucket Module
docs/features/ ├── README.md ├── bucket-creation.feature # Core functionality ├── encryption-configuration.feature # Security ├── lifecycle-policies.feature # Advanced └── access-logging.feature # Observability
Pattern B: Grouped Structure (Complex Modules)
When to use: Modules with 5-15 capabilities or clear domain groupings
docs/features/
├── README.md
├── core/
│ ├── service-creation.feature
│ └── task-definition.feature
├── integration/
│ ├── load-balancer.feature
│ ├── service-discovery.feature
│ └── service-connect.feature
├── security/
│ ├── iam-roles.feature
│ ├── security-groups.feature
│ └── secrets-management.feature
└── observability/
├── cloudwatch-logs.feature
├── cloudwatch-metrics.feature
└── container-insights.feature
Example: ECS Service Module
docs/features/
├── README.md
├── core/
│ ├── fargate-service.feature
│ └── ec2-service.feature
├── networking/
│ ├── vpc-integration.feature
│ ├── load-balancer.feature
│ └── service-mesh.feature
└── scaling/
├── auto-scaling.feature
└── capacity-planning.feature
Pattern C: Layered Structure (Very Complex Modules)
When to use: Modules with >15 capabilities or multiple integration patterns
docs/features/
├── README.md
├── 01-essentials/
│ ├── basic-setup.feature
│ └── minimal-config.feature
├── 02-common-patterns/
│ ├── web-application.feature
│ ├── api-service.feature
│ └── background-worker.feature
├── 03-integrations/
│ ├── aws-services/
│ │ ├── alb-integration.feature
│ │ ├── nlb-integration.feature
│ │ └── route53-integration.feature
│ └── service-mesh/
│ ├── app-mesh.feature
│ └── service-connect.feature
└── 04-advanced/
├── multi-region.feature
├── blue-green-deployment.feature
└── canary-deployment.feature
Terraform-Specific Patterns
Core Infrastructure Features
Group by resource lifecycle:
docs/features/ ├── resource-creation.feature # terraform apply ├── resource-updates.feature # terraform apply (updates) ├── resource-deletion.feature # terraform destroy └── state-management.feature # import, state operations
Integration Testing Features
Group by integration points:
docs/features/ ├── aws-integration.feature # AWS provider ├── module-composition.feature # Using other modules ├── data-sources.feature # External data └── provider-configuration.feature # Multi-region, aliases
Validation Features
Group by validation type:
docs/features/ ├── input-validation.feature # Variable validation ├── output-validation.feature # Output values ├── state-validation.feature # State file checks └── plan-validation.feature # Plan output checks
README.md Organization
Feature Index Template
# Gherkin Feature Specifications Feature files documenting the behavior of this Terraform module. ## Core Features Essential functionality: - [Service Creation](./ecs-service-creation.feature) - Creating ECS Fargate services - [Task Definition](./task-definition-config.feature) - Task configuration and containers ## Integration Features External service integrations: - [Load Balancer](./load-balancer-integration.feature) - ALB/NLB integration - [Service Connect](./service-connect.feature) - Service mesh integration - [Route53](./route53-dns.feature) - DNS configuration ## Security Features Security and compliance: - [IAM Roles](./iam-configuration.feature) - Task and execution roles - [Security Groups](./security-groups.feature) - Network security - [Secrets](./secrets-management.feature) - Secrets Manager integration ## Observability Features Monitoring and logging: - [CloudWatch Logs](./cloudwatch-logging.feature) - Container logging - [CloudWatch Metrics](./cloudwatch-metrics.feature) - Service metrics - [Container Insights](./container-insights.feature) - Enhanced monitoring ## Advanced Features Optional capabilities: - [Auto-scaling](./auto-scaling-policies.feature) - Service auto-scaling - [Blue-Green](./blue-green-deployment.feature) - Deployment strategies ## Test-Driven Workflow 1. Write feature scenarios (this directory) 2. Generate tests from scenarios (`tests/`) 3. Implement module code (`main.tf`, etc.) 4. Validate with `terraform test` 5. Document in README.md 6. Create examples (`examples/`) ## Conventions - **File naming:** kebab-case.feature - **Location:** `docs/features/` - **One feature per file:** Focus on single capability - **Scenario count:** 5-15 scenarios per feature - **Background:** Shared setup when 3+ scenarios need it
Anti-Patterns to Avoid
❌ Anti-Pattern 1: Feature-Coupled Step Definitions
Problem: Steps that only work in specific features
# ecs-service.feature Scenario: Create ECS service Given I have ECS prerequisites # Step only defined for ECS features
Solution: Generic, reusable steps
Scenario: Create ECS service
Given I have the following resources:
| type | name |
| VPC | vpc-123 |
| Cluster | production |
# Generic "I have resources" step works everywhere
❌ Anti-Pattern 2: Too Many Feature Files
Problem: One feature per scenario
docs/features/ ├── scenario-1.feature (1 scenario) ├── scenario-2.feature (1 scenario) ├── scenario-3.feature (1 scenario) # 50+ feature files...
Solution: Group related scenarios
docs/features/ ├── service-creation.feature (10 scenarios) ├── load-balancer.feature (8 scenarios) └── auto-scaling.feature (7 scenarios)
❌ Anti-Pattern 3: Everything in One File
Problem: All scenarios in one massive file
Feature: Complete ECS Module # 50+ scenarios covering everything # 1000+ lines # Impossible to navigate
Solution: Split by domain
docs/features/
├── core/
│ ├── service-creation.feature
│ └── task-definition.feature
└── integration/
├── load-balancer.feature
└── service-discovery.feature
❌ Anti-Pattern 4: Inconsistent Naming
Problem: Mixed naming conventions
docs/features/ ├── ECS_Service.feature ├── load-balancer-integration.feature ├── autoScaling.feature └── Security.Groups.feature
Solution: Consistent kebab-case
docs/features/ ├── ecs-service-creation.feature ├── load-balancer-integration.feature ├── auto-scaling-policies.feature └── security-group-rules.feature
Migration Strategies
From Monolithic to Organized
Step 1: Analyze current feature
# Count scenarios grep "^ Scenario:" docs/features/everything.feature | wc -l # Identify groups grep "^ Scenario:" docs/features/everything.feature | \ sed 's/Scenario: //' | \ sort
Step 2: Create groups
# Identify natural boundaries - Service creation scenarios → service-creation.feature - Load balancer scenarios → load-balancer.feature - Security scenarios → security-configuration.feature
Step 3: Split file
# Extract scenarios by pattern # Create new feature files # Move related scenarios # Update README.md index
Step 4: Validate
# Run tests to ensure nothing broke terraform test # Check for duplicate steps grep "^ Given\|^ When\|^ Then" docs/features/*.feature | \ sort | uniq -d
Best Practices Checklist
File Organization:
- • Features grouped by domain concept
- • File names use kebab-case
- • 5-15 scenarios per feature file
- • README.md indexes all features
- • Directory structure matches module complexity
Scenario Organization:
- • Background used for shared setup (3+ scenarios)
- • Scenario Outline used for parameterized tests
- • Each scenario tests one specific behavior
- • Scenarios are independent (can run in any order)
Step Definition Organization:
- • Steps are reusable across features
- • No feature-coupled step definitions
- • Generic steps with parameters preferred
- • Implementation details abstracted into helpers
Maintenance:
- • No duplicate scenarios
- • Consistent naming across all files
- • Clear feature descriptions
- • Tags used for organization (@smoke, @integration)
Integration with Terraform Module Structure
Alignment with Module Files
terraform-aws-ecs-service/ ├── docs/ │ └── features/ │ ├── ecs-service.feature ← Tests main.tf │ ├── security-groups.feature ← Tests security-group.tf │ ├── iam-roles.feature ← Tests iam-role-policies.tf │ └── auto-scaling.feature ← Tests scaling.tf ├── main.tf ├── security-group.tf ├── iam-role-policies.tf └── scaling.tf
Alignment with Tests
tests/ ├── basic.tftest.hcl ← From ecs-service.feature ├── security-groups.tftest.hcl ← From security-groups.feature ├── iam-roles.tftest.hcl ← From iam-roles.feature └── auto-scaling.tftest.hcl ← From auto-scaling.feature
References
- •Step Organization: https://cucumber.io/docs/gherkin/step-organization/
- •Anti-Patterns: https://cucumber.io/docs/guides/anti-patterns/
- •File Structure Instructions:
.github/instructions/file-structure.instructions.md - •Scenario Shaper Agent:
.github/agents/scenario-shaper.md - •Gherkin Scenarios Skill:
.github/skills/gherkin-scenarios/SKILL.md
Quick Start
- •Identify domain concepts in your module
- •Create feature files following naming convention
- •Group related scenarios (5-15 per file)
- •Use Background for shared setup
- •Abstract steps for reusability
- •Update README.md with feature index
- •Validate with
terraform test