ProgramGuru

Writing Unit Tests

Writing Unit Tests — why it matters

A unit test exercises one behavior with controlled inputs and explicit expectations. Arrange the inputs, act by calling the unit, then assert an observable result. Test edge cases and failure paths rather than only the happiest example.

What you’ll learn

  • Explain writing unit tests and the problem it solves.
  • Identify the relevant compile-time checks and runtime responsibilities.
  • Run the example, predict its output, and try a realistic modification.

Understand the mechanism

The table drives three independent checks, including the boundary at age 18. Throwing stops execution if the observed result differs from the declared expectation.

A test that only prints a result without comparing it to an expected value may not detect regressions.

Follow the concept flow

Writing Unit Tests — concept flowArrange cases → Act on isAdult → Assert each resultWriting Unit Tests1Arrange cases2Act on isAdult3Assert each resultTests exercise behavior, while types check static contracts.
Follow the responsibilities from input to checked result.

Run the primary TypeScript example

Save as writing-unit-tests.ts. The following program passed strict TypeScript compilation, and the displayed output was captured by executing its emitted JavaScript with Node.js 22.16.0.

TypeScript source

function isAdult(age: number): boolean { return age >= 18; }
const cases = [{ input: 17, expected: false }, { input: 18, expected: true }, { input: 30, expected: true }];
for (const test of cases) {
  if (isAdult(test.input) !== test.expected) throw new Error(`Age ${test.input} failed`);
}
console.log(`${cases.length} unit cases passed`);

Verified output

3 unit cases passed

Compile: npx tsc --strict --target es2022 --module commonjs writing-unit-tests.ts; run: node writing-unit-tests.js. For Node.js API examples, install @types/node first. For browser projects, use the browser-specific instructions below.

The example demonstrates the code-level behavior; the related configuration or test commands are shown separately when needed.

Trace the result

The table drives three independent checks, including the boundary at age 18. Throwing stops execution if the observed result differs from the declared expectation.

Predict what changes if you alter one input. Then run the code to compare your reasoning with the real output.

Try the full tool or configuration workflow

Practical project lab: These are real configuration and source-file examples, not a TypeScript object that merely describes settings. Place the files at the named paths relative to one project directory.

age.ts

export const adult = (age:number) => age>=18;

age.test.ts

import { test } from "node:test";
import { strict as assert } from "node:assert";
import { adult } from "./age";
test("boundary",()=> { assert.equal(adult(17),false); assert.equal(adult(18),true); });

Commands

npx tsc --strict --module commonjs --target es2022 age.ts age.test.ts
node --test age.test.js

Use separate cases with names and assertions to improve failure messages.

This local compiler or test-runner mini-project was validated in addition to the primary program.

Common mistake and correction

A test that only prints a result without comparing it to an expected value may not detect regressions.

Identify whether the failure is a type-checking issue, a configuration issue, or a runtime behavior issue before choosing a fix.

Practice the concept

Add cases for age 0 and a negative age; decide whether negative input should throw or return false.

Write down your expected result first. For configuration examples, compare compiler output and diagnostics; for test examples, make the assertion fail deliberately to verify that the tool reports it.

Check your understanding

Which statement makes a trustworthy TypeScript testing practice?
Choose one answer. You can try again.

Answer and explanation

A test must exercise behavior and assert an expected outcome; compiler checks and test results provide different evidence.

The table drives three independent checks, including the boundary at age 18. Throwing stops execution if the observed result differs from the declared expectation.

What to remember

A unit test exercises one behavior with controlled inputs and explicit expectations.

Run the primary example, then complete the practice task or environment-specific lab.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Testing with Vitest or Jest →