Coverage thresholds fail CI khi coverage rơi xuống dưới mức tối thiểu — enforced trong jest.config.js với coverageThreshold.
- Global threshold:
{ global: { branches: 80, functions: 80, lines: 85, statements: 85 } }— áp dụng cho toàn bộ codebase. - Per-file threshold:
{ './src/services/payment.ts': { branches: 95, lines: 95 } }— critical business logic cần coverage cao hơn. - Coverage collectors: Istanbul (mặc định Jest) vs V8 (native, nhanh hơn,
coverageProvider: 'v8'). - Exclude files:
coveragePathIgnorePatterns: ['/node_modules/', '/dist/', '.stories.']— không count generated files, stories, test helpers. - Branch coverage là metric quan trọng nhất — 80% branch nghĩa là nhiều if/else paths được test; statement/line coverage dễ inflate.
Pitfall: đặt threshold quá cao ngay từ đầu gây friction; bắt đầu thấp (60-70%) rồi tăng dần; không chase 100% cho toàn bộ codebase — UI components layout tests có coverage thấp không có nghĩa là nguy hiểm. --collectCoverageFrom: ['src/*/.{ts,tsx}', '!src/*/.d.ts'] đảm bảo files không có tests được tính vào coverage (không chỉ tính files được import bởi tests).