Unit 15 · lesson

A Test Case Starts With a Requirement, Not an Annotation

Before you write @Test, decide what behavior must be true.

Suppose the requirement says:

A method classifies scores from 0 through 100. Values 90 through 100 are HIGH, 70 through 89 are PASS, 0 through 69 are RETRY, and values outside 0 through 100 are invalid.

That requirement already contains test partitions and boundaries.

Concept flow

A test is an executable claim derived from a requirement

Purposeful partitions and boundaries produce stronger evidence than random examples.

  1. REQUIREMENTdefine observable behavior and invalid states
    derive
  2. CASESchoose equivalence classes and boundary values
    predict
  3. EXPECTEDstate the result before execution
    run
  4. ACTUALobserve implementation behavior
    compare
  5. VERDICTpass, fail, fix, and run regression evidence

Derive the cases

Representative cases:

inputexpected
-1invalid
0RETRY
69RETRY
70PASS
89PASS
90HIGH
100HIGH
101invalid

Why test 69 and 70 instead of random values 54 and 77? Because 69/70 straddle a decision boundary.

Equivalence classes reduce pointless repetition

If every score from 70 through 89 should follow the same rule, you do not need thirty identical tests merely to prove diligence.

Choose representative values plus boundaries.

That creates stronger evidence with fewer cases.

Browser-core test harness

You can practice test design without JUnit:

String classify(int score) {
    if (score < 0 || score > 100) return "INVALID";
    if (score >= 90) return "HIGH";
    if (score >= 70) return "PASS";
    return "RETRY";
}

void check(String name, String expected, String actual) {
    String status = expected.equals(actual) ? "PASS" : "FAIL";
    IO.println(name + " | " + status + " | expected=" + expected + " actual=" + actual);
}

This is not JUnit. It is a deterministic test harness for the browser lane.

Tests can be wrong

If you accidentally expect HIGH for score 89 and the implementation correctly returns PASS, the failing test does not prove the program is wrong.

Requirements are the authority. Tests are executable claims about requirements and can contain defects too.

Test one method with an actual defect

Create a method with a boundary bug, such as score > 90 instead of score >= 90.

Run a case at 90, correct the responsible condition, then rerun nearby regression cases 89, 90, and 91.

Evidence

Build a test table for one method with at least six purposeful cases. Label normal behavior, boundaries, and invalid input.

A large number of tests is not automatically better. The set should make the decision boundaries difficult to hide.