Features
Coverage Tracking

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:

  1. Scenario → Test: Which test files validate this acceptance criterion?
  2. Test → Implementation: Which code files does this test exercise?
  3. 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 credentials

Natural 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-validation

Step 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 dashboard

Test 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-validation allowed)

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 1

When 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-62

What this does:

  1. Validates @step comments (for story/bug work units)
  2. Creates test mapping in coverage file
  3. Sets scenario status to ⚠️ PARTIALLY COVERED
  4. 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-24

Line format options:

  • Range: 10-24 (lines 10 through 24)
  • Comma-separated: 10,11,12,23,24 (specific lines)

What this does:

  1. Finds existing test mapping
  2. Adds implementation mapping
  3. Sets scenario status to ✅ FULLY COVERED
  4. 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-24

Convenience 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" \
  --all

Remove specific test mapping:

fspec unlink-coverage user-authentication \
  --scenario "Login with valid credentials" \
  --test-file src/__tests__/auth.test.ts

Remove 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.ts

Viewing Coverage Reports

Single Feature Coverage

fspec show-coverage user-authentication

Output:

# 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 session

Project-Wide Coverage

fspec show-coverage

Shows 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 covered

JSON Output for CI/CD

fspec show-coverage user-authentication --format=json

Machine-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-authentication

Successful audit:

✅ All files found (8/8)
All mappings valid

Failed 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 file

Use 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 update

Use Case 2: Compliance Tracking

Prove requirements are tested and implemented:

fspec show-coverage --format=json --output=compliance-report.json

Generates machine-readable proof of traceability for audits.

Use Case 3: Onboarding New Developers

New developer asks: "How does login work?"

fspec show-coverage user-authentication

Shows 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 verify

Decision Flow: When to Update Coverage

Troubleshooting

Issue: Coverage file not found

Error: Coverage file not found for feature X

Solution:

fspec generate-coverage

Issue: Audit shows broken paths

Error: File not found: src/old-path/file.ts

Solution:

fspec audit-coverage feature-name --fix

Or update manually:

fspec unlink-coverage feature --scenario "X" --all
fspec link-coverage feature --scenario "X" \
  --test-file new-path/test.ts --test-lines 10-20

Issue: 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-50

Issue: @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 page

Or if it's a task (not story/bug):

fspec link-coverage ... --skip-step-validation

Summary

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 mappings

Core 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.