Skip to main content
โšก Calmops

Test Coverage and Metrics

Test Coverage and Metrics

Test coverage measures how much code is tested. This article covers coverage metrics and best practices.

Introduction

Test coverage provides:

  • Code quality metrics
  • Testing completeness
  • Risk identification
  • Quality gates
  • Improvement tracking

Understanding coverage helps you:

  • Measure test completeness
  • Identify untested code
  • Set quality targets
  • Improve code quality
  • Track progress

Coverage Types

Line Coverage

// โœ… Good: Line coverage
function calculateTotal(items) {
  let total = 0;           // Line 1
  for (const item of items) { // Line 2
    total += item.price;   // Line 3
  }
  return total;            // Line 4
}

// Test covers all lines
test('calculates total', () => {
  expect(calculateTotal([{ price: 10 }, { price: 20 }])).toBe(30);
});

Branch Coverage

// โœ… Good: Branch coverage
function getDiscount(amount) {
  if (amount > 100) {      // Branch 1
    return 0.1;
  } else if (amount > 50) { // Branch 2
    return 0.05;
  } else {                  // Branch 3
    return 0;
  }
}

// Test all branches
test('returns 10% discount for amount > 100', () => {
  expect(getDiscount(150)).toBe(0.1);
});

test('returns 5% discount for amount > 50', () => {
  expect(getDiscount(75)).toBe(0.05);
});

test('returns no discount for amount <= 50', () => {
  expect(getDiscount(30)).toBe(0);
});

Function Coverage

// โœ… Good: Function coverage
function add(a, b) {
  return a + b;
}

function subtract(a, b) {
  return a - b;
}

function multiply(a, b) {
  return a * b;
}

// Test all functions
test('add function', () => {
  expect(add(2, 3)).toBe(5);
});

test('subtract function', () => {
  expect(subtract(5, 3)).toBe(2);
});

test('multiply function', () => {
  expect(multiply(2, 3)).toBe(6);
});

Coverage Configuration

Jest Coverage

// โœ… Good: Jest coverage config
// jest.config.js
module.exports = {
  collectCoverageFrom: [
    'src/**/*.js',
    '!src/index.js',
    '!src/**/*.test.js',
    '!src/**/__mocks__/**'
  ],
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80
    },
    './src/utils/': {
      branches: 90,
      functions: 90,
      lines: 90,
      statements: 90
    }
  },
  coverageReporters: ['text', 'lcov', 'html']
};

// Run coverage
npm test -- --coverage

Coverage Reports

# โœ… Good: Generate coverage report
npm test -- --coverage

# โœ… Good: View HTML report
open coverage/lcov-report/index.html

# โœ… Good: Generate JSON report
npm test -- --coverage --coverageReporters=json

# โœ… Good: Upload to Codecov
npm install --save-dev codecov
codecov

Coverage Metrics

Measuring Coverage

// โœ… Good: Track coverage metrics
const coverageMetrics = {
  lines: 85,
  branches: 80,
  functions: 90,
  statements: 85
};

// โœ… Good: Set targets
const targets = {
  lines: 80,
  branches: 75,
  functions: 80,
  statements: 80
};

// โœ… Good: Check if targets met
function checkCoverage(metrics, targets) {
  for (const [key, value] of Object.entries(targets)) {
    if (metrics[key] < value) {
      console.error(`${key} coverage ${metrics[key]}% below target ${value}%`);
      return false;
    }
  }
  return true;
}

Best Practices

  1. Set realistic targets:

    // โœ… Good: Realistic targets
    coverageThreshold: {
      global: {
        lines: 80,
        branches: 75,
        functions: 80
      }
    }
    
    // โŒ Bad: Unrealistic targets
    coverageThreshold: {
      global: {
        lines: 100,
        branches: 100,
        functions: 100
      }
    }
    
  2. Focus on critical code:

    // โœ… Good: Higher coverage for critical code
    './src/utils/': {
      lines: 95,
      branches: 90
    },
    './src/components/': {
      lines: 80,
      branches: 75
    }
    
    // โŒ Bad: Same coverage for all code
    
  3. Exclude generated code:

    // โœ… Good: Exclude generated code
    collectCoverageFrom: [
      'src/**/*.js',
      '!src/**/*.generated.js',
      '!src/**/__mocks__/**'
    ]
    
    // โŒ Bad: Include everything
    collectCoverageFrom: ['src/**/*.js']
    

Summary

Test coverage is important. Key takeaways:

  • Measure coverage types
  • Set realistic targets
  • Focus on critical code
  • Exclude generated code
  • Track metrics
  • Improve incrementally
  • Use coverage reports
  • Maintain quality gates

Next Steps

Comments