Lessons · TypeScript · edge cases first
Test the ends first: nothing, one, everything the same
Most bugs live at the edges: the empty array, the single item, all items equal, and the division that becomes 0 / 0. Test those first; the middle usually follows.
Hone is a place to practise programming. This is one of its lessons, written out in full and free to read without an account.
What it is for
reduce with no starting value throws on an empty array, and 0 / 0 is NaN that spreads silently. Both pass every list you tried and fail the first time a real user has no data.
How to think about it
For any input ask: what is the smallest possible one? The one-item one? The one where nothing differs? Decide the answer on purpose, write the test, then write the code.
Worked example
const assert = require('assert');function average(xs) {if (xs.length === 0) return null;The empty case, decided on purpose.
return xs.reduce((a, b) => a + b, 0) / xs.length;A starting value, so reduce never sees nothing.
}
assert.strictEqual(average([]), null);Nothing.
assert.strictEqual(average([4]), 4);One.
assert.strictEqual(average([3, 3, 3]), 3);Everything the same.
console.log(average([1, 2, 3, 6]));3
Your turn
Decide the empty case for percent.
function percent(part, whole) {
if (whole === 0) return ;
return Math.round(1000 * part / whole) / 10;
}Solve one with the tests running
The trap
Testing only the happy path. It passes, ships, and the empty array arrives on the first day.