QA
Lesson 2 of 8About 3 min readSuggest an edit

Designing test cases

You can’t test every input. A shipping calculator that takes a weight between 0 and 30 kg has millions of possible values. Test design techniques pick the few that are most likely to reveal bugs.

Equivalence partitioning

Divide inputs into groups that the system should treat the same way, then test one value from each group.

For “weight must be more than 0 and at most 30 kg”:

Partition Example Expected
Below range -5 rejected
Zero 0 rejected
Valid 12.5 price calculated
Above range 31 rejected
Not a number “abc” rejected

If 12.5 works, 13 almost certainly works too, so testing both adds little.

Boundary value analysis

Bugs cluster at the edges of partitions, where someone wrote < instead of <=. Test on each side of every boundary:

0     -> rejected      (lower boundary)
0.01  -> accepted      (smallest valid value)
30    -> accepted      (upper boundary)
30.01 -> rejected      (just above)

Combine the two techniques: one value from the middle of each partition, plus both sides of each boundary.

Decision tables

When several conditions interact, list every combination in a table so none is forgotten. Example: a discount applies to members, or to orders over 100, but never to sale items.

Member Order > 100 Sale item Discount?
yes no no yes
no yes no yes
yes yes no yes
no no no no
yes or no yes or no yes no

Each row becomes a test case, and writing the table often reveals rules the specification never stated.

State transition testing

Some behaviour depends on history. An order moves through states: created -> paid -> shipped -> delivered, with cancelled possible before shipping. Test:

  • every valid transition;
  • important invalid ones: can a shipped order be cancelled? Can it be paid twice?
  • sequences that revisit states, such as a payment that fails and is retried.

Drawing the state diagram first is often the fastest way to find gaps in the requirements.

Error guessing and exploratory testing

Structured techniques find a lot, and experience finds the rest. Common trouble spots include empty input, very long input, Unicode and emoji, leading and trailing spaces, time zones and daylight-saving changes, leap years, concurrent edits, and slow or failing networks.

Exploratory testing is time-boxed, focused investigation with a goal (“try to break checkout with unusual addresses”). Take notes, and turn the bugs you find into automated regression tests.

Writing the test itself

A good test case states:

  • the precondition: what must be true beforehand;
  • the action: exactly what is done;
  • the expected result: specific and observable, such as “error message ‘Weight must be at most 30 kg’ appears”, rather than “it works”.

Name automated tests after the behaviour they check, for example rejects_weight_above_30_kg, so a failure tells you what broke without reading the code.

Next: Test automation in CI

Fast feedback, test data, flaky tests, parallelism and quality gates that people trust.