Interview frequency: …
Short answer
Code coverage measures only whether lines ran, not whether Assertions are correct; Mutation Testing checks test strength by deliberately introducing small errors and ensuring tests fail.
Explanation
You can reach 100% coverage simply by calling functions without writing any assert in the test. Mutation Testing (such as Stryker Mutator) measures the quality of tests by deliberately changing comparison operators (for example, > to <) or deleting lines. If a test still passes after a mutation survives, its assertions are weak.
Code example
// isAdult.js
export const isAdult = (age) => age >= 18;
// isAdult.test.js — 100% line coverage, but a weak assertion
import test from "node:test";
import assert from "node:assert/strict";
test("isAdult", () => {
assert.equal(isAdult(30), true);
assert.equal(isAdult(5), false);
});
// A mutation tool changes >= to > and the test above still passes → the mutant survives.
test("isAdult boundary", () => assert.equal(isAdult(18), true)); // kills it
// Built-in coverage: node --test --experimental-test-coverage
// Mutation testing: npx stryker runCommon mistakes
- Chasing 100% Code Coverage and focusing on trivial lines instead of dangerous edge cases.