Skip to main content

Functions That Fail

A function that can be handed bad input has to say so. The usual way is to throw: on success the function returns its result, on failure it throws an Error that explains what went wrong.

A test for such a function must check both paths: good input returns the right value and does not throw, and bad input really does throw — a function that silently accepts bad input is a bug too.

assert.throws(fn) is the check for the bad path. For a function that returns a promise, the same check is spelled assert.rejects(fn) and is awaited.


The Good Path

For a valid input there is nothing extra to write. Call the function, then compare the value. If the call throws instead, the throw ends the test by itself and the report shows the error — you do not have to check for it first.

Valid input, no error

safeDivide(10, 2) must return 5 and must not throw. The call comes first; an unexpected error would end the test right there. Only then is the value compared.

Prompt
Write a TypeScript test file with a safeDivide function that returns a number and throws a RangeError when the divisor is zero. Test the good path: safeDivide(10, 2) must return 5 and must not throw. Show the passing output.
Output: TypeScript file and captured output
Valid input, no error

The Bad Path

The other half of the contract: bad input must fail. assert.throws takes a small function that makes the call, runs it, and fails if nothing was thrown.

You can also say what should be thrown. Passing the error class as the second argument makes the test fail when some other kind of error comes out.

Bad input must throw

Dividing by zero has to fail. assert.throws calls safeDivide(10, 0) and requires a RangeError. If the function returned a number instead, the test would fail — it accepted input it should have rejected.

Prompt
Write a TypeScript test for the bad path of safeDivide: calling it with divisor 0 must throw. Use assert.throws with RangeError as the expected error. Show the passing output.
Output: TypeScript file and captured output
Bad input must throw

A Table with wantErr

Both paths fit into one table-driven test: give each case a wantErr field saying whether an error is expected. The want field is optional, because a case that throws has no value to compare.

Each subtest looks at wantErr first. Expected failures are checked with assert.throws and stop there; the other cases compare the value as usual.

Good and bad cases in one table

Four cases: three normal divisions and one division by zero with wantErr: true. One loop covers the whole contract of the function, and all four subtests pass.

Prompt
Write a table-driven TypeScript test for safeDivide where each case has a name, the two inputs, an optional expected value and a wantErr boolean. Use awaited t.test subtests; check the expected failure with assert.throws and compare the value for the other cases. Include three normal cases and one division by zero. Show the output.
Output: TypeScript file and captured output
Good and bad cases in one table