What are test coverage and TDD, and what are good testing practices?

3 minintermediatenodejscoveragetddbest-practicesci

Quick Answer

Coverage measures how much code your tests execute (lines, branches, functions) — useful for finding untested areas, but high coverage doesn't guarantee good tests. TDD writes a failing test first, then code to pass it, then refactors. Good practice: test behavior not implementation, keep tests isolated and fast, and run them in CI.

Detailed Answer

Answer:

Test coverage — the percentage of code executed by tests:

jest --coverage

Reports line, branch (both sides of every if), function, and statement coverage.

  • Useful to spot untested code and enforce a floor in CI (coverageThreshold).
  • But it's a weak proxy for quality: 100% coverage with no meaningful assertions tests nothing. Coverage tells you what ran, not whether behavior is correct. Don't chase 100% for its own sake; prioritize critical/complex logic.

TDD (Test-Driven Development) — red/green/refactor:

  1. Red — write a failing test for the next small behavior.
  2. Green — write the minimum code to pass it.
  3. Refactor — clean up with the test as a safety net.
// 1. Red: write this first, watch it fail
test('slugify lowercases and hyphenates', () => {
  expect(slugify('Hello World')).toBe('hello-world');
});
// 2. Green: implement slugify. 3. Refactor.

Benefits: forces you to think about the interface/edge cases first and yields naturally testable design.

Good testing practices:

  • Test behavior, not implementation — assert observable outputs/effects, not private internals, so refactors don't break tests.
  • Isolated & repeatable — no shared state, no order dependence, reset in beforeEach.
  • Fast — mock slow I/O; keep the unit suite in seconds so people run it.
  • Descriptive names — "returns 404 when user is missing" documents intent.
  • Arrange–Act–Assert structure; one behavior per test.
  • Run in CI on every push/PR, with coverage thresholds and failing builds blocking merge.
  • Cover edge cases and error paths, not just the happy path — that's where real bugs live.