Coverage Tracking
Complete traceability from specification to implementation.
Coverage tracking creates an unbroken chain from your Gherkin scenarios to test files to implementation code. It answers three critical questions: Which tests validate which requirements? Which code implements which requirements? What's not covered yet?
The Problem: Lost Traceability
Without coverage tracking, you lose the connection between requirements and code:
Requirements exist → Tests exist → Code exists
But which test validates which requirement?
Which code implements which requirement?
What happens when requirements change?The result: Confusion, duplicate effort, missed requirements, brittle refactoring.
How Coverage Tracking Works
Coverage tracking maintains a three-tier mapping structure:
Three levels of traceability:
- Scenario → Test: Which test files validate this acceptance criterion?
- Test → Implementation: Which code files does this test exercise?
- Complete chain: Scenario → Test → Code (full traceability)
Coverage File Format
Every .feature file has a corresponding .feature.coverage JSON file that stores all mappings.
Example: user-login.feature has user-login.feature.coverage
Coverage Structure
{
"scenarios": [
{
"name": "Login with valid credentials",
"testMappings": [
{
"file": "src/__tests__/auth.test.ts",
"lines": "45-62",
"implMappings": [
{
"file": "src/auth/login.ts",
"lines": [10, 11, 12, 23, 24]
},
{
"file": "src/utils/validation.ts",
"lines": [5, 6, 7]
}
]
}
]
}
],
"stats": {
"totalScenarios": 5,
"coveredScenarios": 3,
"coveragePercent": 60,
"testFiles": ["src/__tests__/auth.test.ts"],
"implFiles": ["src/auth/login.ts", "src/utils/validation.ts"],
"totalLinesCovered": 23
}
}Key points:
- One scenario can have multiple test mappings (integration + unit tests)
- One test can have multiple implementation mappings (tests exercise multiple files)
- Stats are calculated automatically when you link coverage
Three Coverage Levels
❌ Uncovered
Status: No test file has been linked to this scenario.
Meaning: Acceptance criterion exists but isn't validated by any test.
Next step: Write a test file and link it.
⚠️ Partially Covered
Status: Test file exists but no implementation has been linked.
Meaning: Test is written (may or may not be implemented), but the implementation code isn't tracked.
Next step: Link the implementation files that the test exercises.
✅ Fully Covered
Status: Test file AND implementation files are linked.
Meaning: Complete traceability established from scenario to code.
Next step: Maintain the mapping as code changes.
Natural Language Workflow: Forward ACDD
Here's how coverage tracking works in natural language when building new features:
Phase 1: Specifying (Write Scenarios)
YOU: "Create a feature for user authentication."
AI: Creating feature file...
fspec create-feature "User Authentication"
✓ Created spec/features/user-authentication.feature
✓ Created spec/features/user-authentication.feature.coverage (empty)
Let me add scenarios for login functionality...
fspec add-scenario user-authentication "Login with valid credentials"
fspec add-scenario user-authentication "Login with invalid credentials"
✓ Added 2 scenarios to the feature
✓ Coverage file updated (0% coverage - no tests yet)Coverage status: All scenarios are ❌ UNCOVERED
Phase 2: Testing (Write Tests)
YOU: "Write tests for the first scenario."
AI: Writing test file for "Login with valid credentials"...
Creating src/__tests__/auth.test.ts with @step comments...
[creates test file with Gherkin step mapping]
Running tests...
npm test
✗ Tests fail (expected - no implementation yet)
This is the RED phase of TDD. Now linking test to scenario...
fspec link-coverage user-authentication \
--scenario "Login with valid credentials" \
--test-file src/__tests__/auth.test.ts \
--test-lines 45-62
✓ Linked test mapping: src/__tests__/auth.test.ts:45-62
✓ Validated @step comments for all Gherkin steps
✓ Coverage updated: 50% (1/2 scenarios)Coverage status:
- "Login with valid credentials": ⚠️ PARTIALLY COVERED (has test, no impl)
- "Login with invalid credentials": ❌ UNCOVERED
Phase 3: Implementing (Write Code)
AI: Implementing login functionality to make tests pass...
Creating src/auth/login.ts...
[writes implementation code]
Running tests...
npm test
✓ Tests pass! (GREEN phase)
Now linking implementation to establish full traceability...
fspec link-coverage user-authentication \
--scenario "Login with valid credentials" \
--test-file src/__tests__/auth.test.ts \
--impl-file src/auth/login.ts \
--impl-lines 10-24
✓ Added implementation mapping: src/auth/login.ts:10-24
✓ Coverage updated: 50% (1/2 scenarios)Coverage status:
- "Login with valid credentials": ✅ FULLY COVERED
- "Login with invalid credentials": ❌ UNCOVERED
Phase 4: Validating (Check Coverage)
YOU: "Show me the coverage report."
AI: fspec show-coverage user-authentication
# Coverage Report: user-authentication.feature
**Coverage**: 50% (1/2 scenarios)
## Summary
- Total Scenarios: 2
- Covered: 1
- Uncovered: 1
- Test Files: 1
- Implementation Files: 1
## Scenarios
### ✅ Login with valid credentials (FULLY COVERED)
- **Test**: `src/__tests__/auth.test.ts:45-62`
- **Implementation**: `src/auth/login.ts:10,11,12,13,14,15,16,17,18,19,20,21,22,23,24`
### ❌ Login with invalid credentials (UNCOVERED)
- No test mappings
## ⚠️ Coverage Gaps
The following scenarios need test coverage:
- Login with invalid credentialsNatural Language Workflow: Reverse ACDD
When documenting existing code, coverage tracking works differently:
Phase 1: Analysis (Understand Existing Code)
YOU: "Document the existing login functionality."
AI: Analyzing existing code...
Found login functionality in src/routes/auth.ts
Found existing tests in src/__tests__/login.test.ts
But no feature file exists yet.
Creating feature specification from existing code...Phase 2: Create Specs (Reverse Engineer)
AI: fspec create-feature "User Login"
fspec add-scenario user-login "Login with valid credentials"
fspec add-scenario user-login "Login with invalid credentials"
fspec add-scenario user-login "Login with expired session"
✓ Created 3 scenarios based on code analysis
✓ Coverage file created (empty - needs linking)Phase 3: Link Existing Tests (May Be Incomplete)
AI: Linking existing test file (which may not have @step comments yet)...
fspec link-coverage user-login \
--scenario "Login with valid credentials" \
--test-file src/__tests__/login.test.ts \
--test-lines 20-45 \
--skip-validation
✓ Linked test (validation skipped for reverse engineering)
Note: Test may be a skeleton or may not follow Gherkin steps exactly.--skip-validation flag: Bypasses @step comment validation for reverse engineering.
Phase 4: Link Existing Implementation
AI: Linking existing implementation code...
fspec link-coverage user-login \
--scenario "Login with valid credentials" \
--test-file src/__tests__/login.test.ts \
--impl-file src/routes/auth.ts \
--impl-lines 67-89 \
--skip-validation
✓ Added implementation mapping: src/routes/auth.ts:67-89
✓ Coverage updated: 33% (1/3 scenarios)Phase 5: Identify Gaps
AI: fspec show-coverage user-login
# Coverage Report: user-login.feature
**Coverage**: 33% (1/3 scenarios)
## Scenarios
### ⚠️ Login with valid credentials (PARTIALLY COVERED)
- **Test**: `src/__tests__/login.test.ts:20-45` (may need @step comments)
- **Implementation**: `src/routes/auth.ts:67-89`
### ❌ Login with invalid credentials (UNCOVERED)
- No test mappings - CODE EXISTS, NEEDS TEST
### ❌ Login with expired session (UNCOVERED)
- No test mappings - CODE EXISTS, NEEDS TEST
## ⚠️ Coverage Gaps
Reverse ACDD identified 2 scenarios without tests.
Next steps:
1. Write tests for uncovered scenarios
2. Add @step comments to existing tests
3. Re-link without --skip-validationStep Validation: The Critical Link
For story and bug work units, coverage tracking enforces @step comment validation to ensure tests map to Gherkin steps.
What Are @step Comments?
Comments in test files that map to Gherkin steps:
Feature file (user-login.feature):
Scenario: Login with valid credentials
Given I am on the login page
When I enter valid credentials
Then I should see the dashboardTest file (auth.test.ts) - REQUIRED for stories/bugs:
describe('Feature: User Login', () => {
it('should login with valid credentials', () => {
// @step Given I am on the login page
render(<LoginPage />);
// @step When I enter valid credentials
fireEvent.change(screen.getByLabelText('Email'), {
target: { value: 'user@example.com' }
});
fireEvent.click(screen.getByText('Login'));
// @step Then I should see the dashboard
expect(screen.getByText('Dashboard')).toBeInTheDocument();
});
});Validation rules:
- Story work units: @step validation MANDATORY
- Bug work units: @step validation MANDATORY
- Task work units: @step validation OPTIONAL (
--skip-step-validationallowed)
Why Step Validation Matters
Without @step comments, the link between Gherkin and test code is invisible:
Scenario says: "Given I am on the login page"
Test code says: render(<LoginPage />);
How do you know they match? You don't.With @step comments, the link is explicit and verifiable.
Linking Commands
Generate Coverage Files
Create .coverage files for all features:
fspec generate-coverage
# Output:
# ✓ Created 2, Updated 1, Skipped 5, Recreated 1When to run:
- After creating new feature files
- After project setup
- When coverage files are missing or corrupted
Link Test to Scenario
fspec link-coverage user-authentication \
--scenario "Login with valid credentials" \
--test-file src/__tests__/auth.test.ts \
--test-lines 45-62What this does:
- Validates @step comments (for story/bug work units)
- Creates test mapping in coverage file
- Sets scenario status to ⚠️ PARTIALLY COVERED
- Updates statistics
Link Implementation to Test
fspec link-coverage user-authentication \
--scenario "Login with valid credentials" \
--test-file src/__tests__/auth.test.ts \
--impl-file src/auth/login.ts \
--impl-lines 10-24Line format options:
- Range:
10-24(lines 10 through 24) - Comma-separated:
10,11,12,23,24(specific lines)
What this does:
- Finds existing test mapping
- Adds implementation mapping
- Sets scenario status to ✅ FULLY COVERED
- Updates statistics
Link Both at Once
fspec link-coverage user-authentication \
--scenario "Login with valid credentials" \
--test-file src/__tests__/auth.test.ts \
--test-lines 45-62 \
--impl-file src/auth/login.ts \
--impl-lines 10-24Convenience command: Creates both test and implementation mappings in one go.
Remove Coverage Mappings
Remove all mappings for a scenario:
fspec unlink-coverage user-authentication \
--scenario "Login with valid credentials" \
--allRemove specific test mapping:
fspec unlink-coverage user-authentication \
--scenario "Login with valid credentials" \
--test-file src/__tests__/auth.test.tsRemove specific implementation mapping:
fspec unlink-coverage user-authentication \
--scenario "Login with valid credentials" \
--test-file src/__tests__/auth.test.ts \
--impl-file src/auth/login.tsViewing Coverage Reports
Single Feature Coverage
fspec show-coverage user-authenticationOutput:
# Coverage Report: user-authentication.feature
**Coverage**: 67% (2/3 scenarios)
## Summary
- Total Scenarios: 3
- Covered: 2
- Uncovered: 1
- Test Files: 2
- Implementation Files: 2
- Total Lines: 45
## Scenarios
### ✅ Login with valid credentials (FULLY COVERED)
- **Test**: `src/__tests__/auth.test.ts:45-62`
- **Implementation**: `src/auth/login.ts:10,11,12,23,24`
### ✅ Login with OAuth (FULLY COVERED)
- **Test**: `src/__tests__/oauth.test.ts:15-40`
- **Implementation**: `src/auth/oauth.ts:5,6,7,20,21`
### ❌ Login with expired session (UNCOVERED)
- No test mappings
## ⚠️ Coverage Gaps
The following scenarios need test coverage:
- Login with expired sessionProject-Wide Coverage
fspec show-coverageShows all features with aggregate statistics:
# Project Coverage Report
**Overall Coverage**: 75% (45/60 scenarios)
## Project Summary
- Total Features: 12
- Total Scenarios: 60
- Covered: 45
- Uncovered: 15
## Features
### ✅ User Authentication (100% coverage)
- 3/3 scenarios covered
### ⚠️ Payment Processing (67% coverage)
- 2/3 scenarios covered
### ❌ Notifications (0% coverage)
- 0/5 scenarios coveredJSON Output for CI/CD
fspec show-coverage user-authentication --format=jsonMachine-readable output for integration with CI/CD pipelines, quality gates, compliance tracking.
Auditing Coverage
Verify that all files referenced in coverage still exist:
fspec audit-coverage user-authenticationSuccessful audit:
✅ All files found (8/8)
All mappings validFailed audit:
✗ 2 missing file(s) out of 10 total files
❌ Test file not found: src/__tests__/deleted.test.ts
Recommendation: Remove this mapping or restore the deleted file
❌ Implementation file not found: src/auth/old-login.ts
Recommendation: Remove this mapping or restore the deleted fileUse cases:
- After refactoring (files moved/renamed)
- Before releases (verify integrity)
- After git branch merges (detect conflicts)
Integration with ACDD Workflow
Coverage tracking is designed for the ACDD workflow:
ACDD Phase Integration
Specifying Phase:
- Create feature file → Coverage file auto-created
- All scenarios start as ❌ UNCOVERED
Testing Phase:
- Write test with @step comments → Link test → ⚠️ PARTIALLY COVERED
Implementing Phase:
- Write implementation → Link implementation → ✅ FULLY COVERED
Validating Phase:
- Run
fspec show-coverage→ Verify 100% coverage - Audit coverage → Ensure file integrity
Done:
- Coverage files committed to git
- Living documentation maintained
Best Practices
✅ DO
- Link immediately after writing - Test written → Link immediately
- Use specific line ranges - Be precise (45-62, not 1-500)
- Update after refactoring - Line numbers change → Update mappings
- Commit coverage files - They're part of your documentation
- Aim for 100% coverage - Every scenario should have tests
- Audit regularly - Check file integrity before releases
- Use @step comments - Map tests to Gherkin steps explicitly
❌ DON'T
- Batch coverage updates - Update incrementally, not at the end
- Use entire file ranges - Too broad, loses granularity
- Skip @step validation - Only for tasks, not stories/bugs
- Forget to update - Coverage becomes stale after refactoring
- Ignore gaps - Uncovered scenarios are missing requirements
- Delete coverage files - They're your traceability record
Common Use Cases
Use Case 1: Impact Analysis
Scenario changes → Which code needs updating?
fspec show-coverage user-authentication
# Output shows:
# Scenario "Login with valid credentials"
# Test: src/__tests__/auth.test.ts:45-62
# Implementation: src/auth/login.ts:10-24
#
# Now you know EXACTLY which files to updateUse Case 2: Compliance Tracking
Prove requirements are tested and implemented:
fspec show-coverage --format=json --output=compliance-report.jsonGenerates machine-readable proof of traceability for audits.
Use Case 3: Onboarding New Developers
New developer asks: "How does login work?"
fspec show-coverage user-authenticationShows the complete chain: Requirement → Test → Implementation.
Use Case 4: Refactoring Safety
Before refactoring, check what tests will break:
fspec show-coverage user-authentication
# If login.ts:10-24 is mapped, refactoring it will affect auth tests
# Run those tests after refactoring to verifyDecision Flow: When to Update Coverage
Troubleshooting
Issue: Coverage file not found
Error: Coverage file not found for feature X
Solution:
fspec generate-coverageIssue: Audit shows broken paths
Error: File not found: src/old-path/file.ts
Solution:
fspec audit-coverage feature-name --fixOr update manually:
fspec unlink-coverage feature --scenario "X" --all
fspec link-coverage feature --scenario "X" \
--test-file new-path/test.ts --test-lines 10-20Issue: Wrong line numbers after refactoring
Problem: Code moved, line numbers invalid
Solution:
# Remove old mapping
fspec unlink-coverage feature --scenario "X" --all
# Add new mapping
fspec link-coverage feature --scenario "X" \
--test-file test.ts --test-lines 20-35 \
--impl-file impl.ts --impl-lines 40-50Issue: @step validation fails
Error: Missing @step comment for: Given I am on the login page
Solution: Add the comment to your test file:
// @step Given I am on the login pageOr if it's a task (not story/bug):
fspec link-coverage ... --skip-step-validationSummary
Coverage tracking provides complete traceability for ACDD:
Three Tiers:
- Scenario → Test (What validates this requirement?)
- Test → Implementation (What code does this test exercise?)
- Complete chain (Full traceability)
Three Statuses:
- ❌ UNCOVERED (no test)
- ⚠️ PARTIALLY COVERED (test, no impl)
- ✅ FULLY COVERED (test + impl)
Key Commands:
fspec generate-coverage # Create coverage files
fspec link-coverage ... # Link test/impl to scenarios
fspec show-coverage [feature] # View coverage reports
fspec audit-coverage [feature] # Verify file integrity
fspec unlink-coverage ... # Remove mappingsCore Principles:
- Link immediately after writing code
- Update after refactoring
- Aim for 100% coverage
- Audit before releases
- Commit coverage files to git
Coverage tracking transforms requirements from documents into living, verified, traceable artifacts.