Claude Code Plugins

Community-maintained marketplace

Feedback

Strategic regression testing with test selection, impact analysis, and continuous regression management. Use when verifying fixes don't break existing functionality, planning regression suites, or optimizing test execution for faster feedback.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name regression-testing
description Strategic regression testing with test selection, impact analysis, and continuous regression management. Use when verifying fixes don't break existing functionality, planning regression suites, or optimizing test execution for faster feedback.

Regression Testing

Core Principle

Every fix is a risk. Every change can break something.

Regression testing ensures that new changes don't break existing functionality. It's not about testing everything - it's about smartly testing what matters when changes occur.

What is Regression Testing?

Regression: Re-running tests after changes to verify existing functionality still works.

Why needed:

  • Bug fixes can introduce new bugs
  • New features can break old features
  • Refactoring can change behavior
  • Dependency updates can cause failures
  • Environmental changes affect functionality

Goal: Catch unintended side effects early and cheaply.

Types of Regression Testing

1. Corrective Regression (No Code Change)

When: No changes to code, just re-running existing tests

Use case:

  • Environment change (new database version)
  • Configuration change
  • Infrastructure update
  • Verifying test stability

Strategy: Re-run full existing test suite

Example:

# After upgrading Node.js from 18 to 20
npm test  # Run all tests to ensure nothing broke

2. Progressive Regression (New Features)

When: New features added, existing tests still valid

Strategy:

  • Run existing regression suite
  • Add new tests for new features
  • Focus on integration points with existing code

Example:

New Feature: Social login
Regression Focus:
✓ Existing email login still works
✓ User profile creation unchanged
✓ Session management compatible
✓ New social login tests added

3. Selective Regression (Targeted Testing)

When: Specific modules changed, test only impacted areas

Strategy:

  • Analyze code changes
  • Identify dependent modules
  • Run tests for changed + dependent code
  • Skip unrelated tests

Benefits:

  • Faster feedback (minutes vs hours)
  • Resource efficient
  • Scales to large codebases

Example:

// Payment module changed
// Run tests for:
- payment.test.ts ✓
- checkout.test.ts ✓ (depends on payment)
- order-confirmation.test.ts ✓ (depends on payment)
// Skip unrelated:
- user-profile.test.ts ✗ (no dependency)
- search.test.ts ✗ (no dependency)

4. Complete Regression (Full Suite)

When:

  • Major refactoring
  • Before release
  • After significant changes
  • Periodic confidence check

Strategy: Run every test in the suite

Timing:

  • Nightly builds
  • Weekly full regression
  • Pre-release validation

5. Partial Regression (Risk-Based)

When: Time-constrained, need quick validation

Strategy:

  • Run critical path tests
  • Run high-risk area tests
  • Run frequently failing tests
  • Skip low-priority tests

Example:

High Priority (always run):
✓ Login/authentication
✓ Payment processing
✓ Data integrity checks

Medium Priority (run if time):
✓ User profile management
✓ Search functionality

Low Priority (skip in quick regression):
✗ Admin panel features
✗ Reporting dashboards

Test Selection Strategies

Strategy 1: Change-Based Selection

Analyze what changed, test accordingly

// PR changes:
- src/services/payment.ts
- src/utils/currency.ts

// Select tests covering:
- payment.test.ts ✓
- currency.test.ts ✓
- integration/checkout.test.ts ✓ (uses payment)
- e2e/purchase-flow.test.ts ✓ (exercises payment)

Tools:

  • Git diff analysis
  • Code coverage mapping
  • Dependency graphs

Benefits:

  • Fast feedback (5-10 min vs 2 hours)
  • 70-90% defect detection
  • Scalable to large suites

Strategy 2: Risk-Based Selection

Prioritize based on failure risk and impact

Risk Score = Probability of Failure × Impact

High Risk:
- Payment processing (critical + complex)
- Authentication (critical + frequently changed)
- Data migration (high impact)

Medium Risk:
- User profile (moderate impact)
- Search (stable code)

Low Risk:
- Help documentation (low impact + stable)

Strategy 3: Historical Failure Analysis

Test what breaks frequently

// Track test failures over last 30 days
const flakyTests = [
  'checkout.test.ts - 15 failures',
  'auth.test.ts - 12 failures',
  'api-integration.test.ts - 8 failures'
];

// Always include in regression

Strategy 4: Code Coverage-Based

Test code with poor existing coverage

// Coverage analysis
payment.ts: 45% coverage → High priority for regression
checkout.ts: 85% coverage → Medium priority
utils.ts: 95% coverage → Low priority

// Focus regression on under-tested code

Strategy 5: Time-Budget Selection

Fixed time window, maximize value

// You have 15 minutes
const testPriority = [
  { test: 'critical-paths', time: '5 min', value: 'high' },
  { test: 'payment-flows', time: '3 min', value: 'high' },
  { test: 'auth-flows', time: '2 min', value: 'high' },
  { test: 'search', time: '2 min', value: 'medium' },
  { test: 'profiles', time: '3 min', value: 'medium' }
];

// Run until time budget exhausted
// Total: 15 min, covering all high-value tests

Building a Regression Suite

Phase 1: Seed with Critical Tests

Start with smoke tests - does basic functionality work?

// Smoke test suite (5-10 min)
describe('Smoke Tests', () => {
  test('App starts without errors', () => {
    expect(app.isRunning()).toBe(true);
  });

  test('Database connection works', () => {
    expect(db.isConnected()).toBe(true);
  });

  test('Critical API endpoints respond', () => {
    expect(api.health()).toBe('OK');
  });

  test('User can login', () => {
    login('test@example.com', 'password');
    expect(session.isActive()).toBe(true);
  });
});

Phase 2: Add Happy Path Tests

Cover main user workflows end-to-end.

// Happy path suite (20-30 min)
describe('Core User Journeys', () => {
  test('User can sign up and verify email', async () => {
    await signup('new@example.com', 'SecurePass123!');
    const email = await getLatestEmail('new@example.com');
    await verifyEmail(email.verificationLink);
    expect(user.isVerified()).toBe(true);
  });

  test('User can complete purchase', async () => {
    await login();
    await addToCart(product);
    await checkout();
    await submitPayment(validCard);
    expect(order.status()).toBe('completed');
  });
});

Phase 3: Add Edge Cases and Error Scenarios

// Edge case suite (30-45 min)
describe('Edge Cases', () => {
  test('Handles expired credit card', async () => {
    await checkout();
    await submitPayment(expiredCard);
    expect(error.message()).toContain('Card expired');
  });

  test('Handles concurrent checkout attempts', async () => {
    const promises = [
      checkout(user1),
      checkout(user1) // Same user, same time
    ];
    const results = await Promise.all(promises);
    expect(results.filter(r => r.success).length).toBe(1);
  });
});

Phase 4: Add Integration Tests

// Integration suite (45-60 min)
describe('System Integration', () => {
  test('Payment gateway integration works', async () => {
    const result = await paymentGateway.charge(card, amount);
    expect(result.status).toBe('succeeded');
    expect(db.transaction).toHaveBeenRecorded();
    expect(email.receipt).toHaveBeenSent();
  });

  test('Inventory sync with warehouse', async () => {
    await purchaseProduct(product);
    const inventory = await warehouse.checkStock(product.id);
    expect(inventory.quantity).toBe(originalQuantity - 1);
  });
});

Regression Suite Pyramid

         /\
        /  \  Full Regression (weekly)
       /    \  - All tests (2-4 hours)
      /------\
     /        \  Extended Regression (nightly)
    /          \  - All unit + integration + critical E2E (30-60 min)
   /------------\
  /              \  Quick Regression (per commit)
 /________________\  - Changed code tests + smoke tests (5-10 min)

Test Impact Analysis

Mapping Tests to Code

Build dependency graph:

// Track which tests cover which code
const testCoverage = {
  'payment.ts': [
    'payment.test.ts',
    'checkout.integration.test.ts',
    'e2e/purchase.test.ts'
  ],
  'user.ts': [
    'user.test.ts',
    'auth.integration.test.ts',
    'e2e/signup.test.ts'
  ]
};

// When payment.ts changes, run all related tests
function selectTests(changedFiles) {
  const testsToRun = new Set();
  changedFiles.forEach(file => {
    testCoverage[file]?.forEach(test => testsToRun.add(test));
  });
  return Array.from(testsToRun);
}

Transitive Dependencies

Account for indirect dependencies:

// Direct dependency
payment.ts → uses → currency.ts

// Transitive dependency
checkout.ts → uses → payment.ts → uses → currency.ts

// When currency.ts changes, test:
- currency.test.ts (direct)
- payment.test.ts (direct dependency on currency)
- checkout.test.ts (transitive dependency)

Static Analysis for Test Selection

// Analyze imports to build dependency graph
import ts from 'typescript';

function findDependencies(sourceFile: string): string[] {
  const program = ts.createProgram([sourceFile], {});
  const checker = program.getTypeChecker();

  // Extract all imports
  const dependencies = [];
  const sourceFileObj = program.getSourceFile(sourceFile);

  ts.forEachChild(sourceFileObj, node => {
    if (ts.isImportDeclaration(node)) {
      dependencies.push(node.moduleSpecifier.text);
    }
  });

  return dependencies;
}

Regression Test Optimization

Technique 1: Test Parallelization

Run tests concurrently for faster feedback

// Sequential: 60 min
test1(); // 20 min
test2(); // 20 min
test3(); // 20 min

// Parallel: 20 min
Promise.all([
  test1(), // 20 min
  test2(), // 20 min
  test3()  // 20 min
]);

// Jest configuration
module.exports = {
  maxWorkers: '50%', // Use half CPU cores
  testTimeout: 30000
};

Technique 2: Test Sharding

Distribute tests across multiple machines

# CI pipeline with 4 workers
jobs:
  test:
    strategy:
      matrix:
        shard: [1, 2, 3, 4]
    steps:
      - run: npm test -- --shard=${{ matrix.shard }}/4

# Each worker runs 25% of tests
# Total time: 60 min / 4 = 15 min

Technique 3: Incremental Testing

Test only what changed since last run

// Track test results
const lastRun = {
  timestamp: '2025-10-24T10:00:00Z',
  passed: ['test1', 'test2', 'test3'],
  failed: []
};

// Current run
const currentChanges = ['payment.ts', 'checkout.ts'];

// Run:
// 1. Tests for changed code (payment, checkout)
// 2. Tests that failed last time (if any)
// Skip tests that passed last time for unchanged code

Technique 4: Smoke Test Fast Fail

Run fastest, most critical tests first

# CI Pipeline
stages:
  - smoke-test:     # 2 min
      - critical-paths
      - fail-fast: true  # Stop if smoke fails

  - quick-regression: # 10 min
      - changed-code-tests
      - fail-fast: true

  - full-regression:  # 60 min
      - all-tests
      - fail-fast: false  # Run all to find all issues

Technique 5: Test Flakiness Removal

Eliminate unreliable tests

// Track test stability over 100 runs
const testStability = {
  'reliable-test': { runs: 100, passes: 100, passRate: 1.00 },
  'flaky-test': { runs: 100, passes: 87, passRate: 0.87 },
  'unstable-test': { runs: 100, passes: 64, passRate: 0.64 }
};

// Strategy:
// passRate >= 0.98 → Keep in regression suite
// passRate 0.90-0.98 → Fix flakiness
// passRate < 0.90 → Quarantine until fixed

// Flaky tests waste time and reduce confidence

Continuous Regression Testing

Regression in CI/CD Pipeline

# .github/workflows/regression.yml
name: Regression Testing

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]
  schedule:
    - cron: '0 2 * * *'  # Nightly at 2 AM

jobs:
  quick-regression:
    name: Quick Regression (per PR)
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v3
      - name: Changed file analysis
        id: changes
        uses: dorny/paths-filter@v2
        with:
          filters: |
            payment:
              - 'src/payment/**'
            auth:
              - 'src/auth/**'

      - name: Run affected tests
        run: |
          npm run test:payment
          npm run test:auth
        if: steps.changes.outputs.payment == 'true' || steps.changes.outputs.auth == 'true'

      - name: Smoke tests (always)
        run: npm run test:smoke

  nightly-regression:
    name: Nightly Full Regression
    runs-on: ubuntu-latest
    timeout-minutes: 120
    if: github.event_name == 'schedule'
    steps:
      - name: Run all tests
        run: npm test

      - name: Coverage report
        run: npm run coverage

      - name: Upload results
        uses: actions/upload-artifact@v3
        with:
          name: regression-results
          path: test-results/

Pre-Commit Regression

Local regression before committing

# .git/hooks/pre-commit
#!/bin/bash

echo "Running quick regression tests..."

# Get staged files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep ".ts$")

if [ -z "$STAGED_FILES" ]; then
  echo "No TypeScript files changed, skipping tests"
  exit 0
fi

# Run tests for changed files
npm run test:changed -- $STAGED_FILES

if [ $? -ne 0 ]; then
  echo "❌ Regression tests failed. Commit aborted."
  exit 1
fi

echo "✅ Regression tests passed"
exit 0

Pre-Deployment Regression

Final validation before production

# Deployment pipeline
deploy:
  steps:
    - name: Production smoke tests
      run: npm run test:smoke:production
      env:
        API_URL: https://staging.example.com

    - name: Critical path regression
      run: npm run test:critical-paths

    - name: Security regression
      run: npm run test:security

    - name: Performance baseline check
      run: npm run test:performance

    - name: Deploy to production
      if: success()
      run: ./deploy.sh production

Regression Test Maintenance

Anti-Pattern: Test Rot

Problem: Tests become outdated, irrelevant, or broken

// BAD: Outdated test
test('User can pay with PayPal', () => {
  // PayPal integration removed 6 months ago
  // Test still exists but is meaningless
});

// GOOD: Remove obsolete tests
// Delete test when feature is removed

Strategy: Regular Test Review

## Quarterly Test Audit

Review each test:
- [ ] Is feature still in product?
- [ ] Does test provide value?
- [ ] Is test reliable (not flaky)?
- [ ] Is test documented/understandable?
- [ ] Execution time acceptable?

Actions:
- Delete: Obsolete tests
- Fix: Flaky tests
- Optimize: Slow tests
- Document: Unclear tests
- Consolidate: Duplicate tests

Strategy: Test Suite Metrics

interface TestSuiteHealth {
  totalTests: number;
  executionTime: string;
  passRate: number;
  flakiness: number;
  coverage: number;
  lastUpdated: Date;
}

const regressionHealth: TestSuiteHealth = {
  totalTests: 1247,
  executionTime: '18 min',
  passRate: 0.987,        // 98.7% pass rate
  flakiness: 0.013,       // 1.3% flaky tests (target: <2%)
  coverage: 0.82,         // 82% code coverage
  lastUpdated: new Date('2025-10-24')
};

// Track over time
// Trend: execution time ↑ → need optimization
// Trend: flakiness ↑ → need stabilization
// Trend: coverage ↓ → add tests for new code

Strategy: Test Ownership

// tests/payment/checkout.test.ts
/**
 * @owner team-payments
 * @created 2025-06-15
 * @criticality high
 * @executionTime 45s
 * @lastReview 2025-09-20
 *
 * Tests the complete checkout flow including:
 * - Cart validation
 * - Payment processing
 * - Order confirmation
 * - Email receipt
 */

// Benefits:
// - Clear responsibility for maintenance
// - Context for why test exists
// - Trigger for regular review

Regression Testing Best Practices

✅ DO: Automate Regression Tests

Manual regression doesn't scale

// Automated regression runs on every PR
// Catches issues in minutes, not days

✅ DO: Use Descriptive Test Names

// BAD
test('test1', () => { ... });

// GOOD
test('checkout fails gracefully when payment gateway is down', () => {
  mockPaymentGateway.simulateOutage();
  const result = await checkout(cart);
  expect(result.status).toBe('payment-failed');
  expect(result.userMessage).toContain('payment service unavailable');
});

✅ DO: Keep Tests Independent

// BAD: Tests depend on execution order
test('create user', () => {
  user = createUser('test@example.com');
});

test('user can login', () => {
  login(user); // Fails if previous test didn't run
});

// GOOD: Each test independent
test('user can login', () => {
  const user = createUser('test@example.com'); // Setup in test
  login(user);
  expect(session.isActive()).toBe(true);
});

✅ DO: Use Setup/Teardown

describe('Payment Tests', () => {
  beforeEach(async () => {
    // Clean slate for each test
    await db.clean();
    await db.seed(testData);
  });

  afterEach(async () => {
    // Cleanup
    await db.clean();
  });

  test('payment succeeds with valid card', async () => {
    // Test has clean environment
  });
});

❌ DON'T: Test Everything, Every Time

// DON'T run 4-hour full regression on every commit
// DO run smart selection based on changes

❌ DON'T: Ignore Flaky Tests

// DON'T keep flaky tests and ignore failures
// DO fix or quarantine flaky tests immediately

❌ DON'T: Duplicate Test Coverage

// DON'T test same thing at multiple levels
// Unit test: currency conversion logic
// Integration test: currency conversion in payment
// E2E test: full purchase with currency conversion

// DO test each concern at appropriate level
// Unit: Conversion logic
// Integration: Payment service uses conversion correctly
// E2E: Happy path only (one currency conversion example)

Using with QE Agents

Intelligent Test Selection

qe-regression-risk-analyzer performs smart test selection:

// Analyze PR for regression risk
const analysis = await agent.analyzeRegressionRisk({
  pr: 1234,
  strategy: 'change-based-with-risk',
  timebudget: '15min'
});

// Returns:
// {
//   mustRun: ['payment.test.ts', 'checkout.integration.test.ts'],
//   shouldRun: ['order.test.ts', 'inventory.test.ts'],
//   canSkip: ['profile.test.ts', 'search.test.ts'],
//   estimatedTime: '12 min',
//   riskCoverage: 0.94
// }

Automated Test Generation for Regression

qe-test-generator creates regression tests from bugs:

// Bug found in production
const bug = {
  id: 'BUG-567',
  description: 'Checkout fails when user has > 100 items in cart',
  severity: 'high'
};

// Agent generates regression test
await agent.generateRegressionTest({
  bug: bug,
  preventRecurrence: true
});

// Creates:
// tests/regression/BUG-567-large-cart.test.ts
test('checkout succeeds with 100+ items in cart', async () => {
  const cart = generateCart(150); // Edge case that failed
  const result = await checkout(cart);
  expect(result.status).toBe('success');
});

Continuous Regression Monitoring

qe-quality-analyzer tracks regression suite health:

// Monitor regression suite metrics
const health = await agent.analyzeRegressionHealth({
  suite: 'main-regression',
  period: '30d'
});

// Returns insights:
// {
//   executionTimeTrend: 'increasing', // ⚠️ Getting slower
//   flakinessRate: 0.03,              // ⚠️ Above 2% threshold
//   coverageTrend: 'stable',          // ✅ Maintaining coverage
//   recommendations: [
//     'Parallelize slow tests',
//     'Fix 12 flaky tests',
//     'Remove 5 obsolete tests'
//   ]
// }

Regression Testing in CI/CD

qe-test-executor orchestrates regression runs:

// Execute smart regression in CI pipeline
await agent.executeRegression({
  trigger: 'pull-request',
  strategy: 'selective',
  changedFiles: ['src/payment/stripe.ts', 'src/models/order.ts'],
  parallel: true,
  failFast: false
});

// Execution plan:
// 1. Analyze changed files
// 2. Select impacted tests (change-based)
// 3. Add critical path tests (risk-based)
// 4. Run in parallel across 4 workers
// 5. Report results with coverage metrics

Visual Regression Testing

qe-visual-tester catches UI regressions:

// Detect visual changes after code update
await agent.visualRegression({
  baseline: 'main-branch',
  current: 'feature-branch',
  pages: ['checkout', 'product-detail', 'cart'],
  threshold: 0.01 // 1% pixel difference tolerance
});

// Returns:
// {
//   changed: ['checkout-page'],
//   diff: {
//     'checkout-page': {
//       pixelDifference: 234,
//       percentageChange: 0.023,
//       screenshot: 'diff-checkout.png',
//       verdict: 'review-required'
//     }
//   }
// }

Fleet-Coordinated Regression

// Multiple agents collaborate on regression testing
const regressionFleet = await FleetManager.coordinate({
  strategy: 'comprehensive-regression',
  agents: [
    'qe-regression-risk-analyzer',  // 1. Analyze changes, select tests
    'qe-test-generator',            // 2. Generate missing regression tests
    'qe-test-executor',             // 3. Execute selected tests
    'qe-coverage-analyzer',         // 4. Analyze coverage gaps
    'qe-visual-tester',             // 5. Check visual regressions
    'qe-quality-gate'               // 6. Make GO/NO-GO decision
  ],
  topology: 'sequential'
});

// Execute full regression workflow
const result = await regressionFleet.execute({
  pr: 1234,
  release: 'v3.2.0',
  riskTolerance: 'low'
});

// Returns comprehensive regression report

Production Regression Detection

qe-production-intelligence detects regressions in production:

// Monitor production for regression signals
await agent.detectProductionRegression({
  baseline: 'v3.1.0',
  current: 'v3.2.0',
  metrics: ['error-rate', 'latency', 'conversion'],
  alertThreshold: 0.1 // 10% degradation
});

// Alerts if:
// - Error rate increases > 10%
// - Latency degrades > 10%
// - Conversion drops > 10%

// Enables fast rollback before major impact

Related Skills

Core Quality Practices:

Testing Approaches:

Development Practices:

Communication:


Remember

Regression testing is insurance against change.

Every code change is a risk. Regression testing mitigates that risk by:

  • Verifying existing functionality still works
  • Catching unintended side effects early
  • Building confidence for continuous deployment
  • Enabling safe refactoring and evolution

Good regression testing is strategic, not exhaustive.

You cannot test everything, every time. Smart regression testing:

  • Selects tests based on changes and risk
  • Runs fast enough for continuous feedback
  • Maintains reliability (no flaky tests)
  • Evolves with the product

Perfect regression coverage is impossible. Effective regression testing is achievable.

With Agents: Agents excel at intelligent test selection, impact analysis, automated test generation from bugs, and continuous regression monitoring. Use agents to make regression testing data-driven, efficient, and scalable.