×

php · level 3 · unit 7 · lesson 4

  1. meet it
  2. guess first
  3. your turn
  4. fix it
  5. nailed it

Tap a green word if you get lost.

meet it

Test the edges, where bugs love to hide.

Code usually works for the obvious input. Bugs hide at the edges: empty strings, zero, negative numbers, the exact limit and one past it. Every deserves its own test. So does bad input that your code should refuse, which means checking that it throws.

An assert_throws helper runs a closure and passes only if the right exception escapes. InvalidArgumentException::class gives a class's name as a string. Keep every test and re-run them all after each change, and a is caught before your users find it.

<?php
function assert_throws(string $name, string $class, callable $action): void {
    try {
        $action();
        echo "FAIL $name: nothing was thrown\n";
    } catch (Throwable $e) {
        echo $e instanceof $class ? "PASS $name\n" : "FAIL $name: got " . get_class($e) . "\n";
    }
}
function quantity(int $n): int {
    if ($n < 1 || $n > 10) { throw new InvalidArgumentException("Choose 1 to 10, not $n."); }
    return $n;
}
assert_throws("refuses 0", InvalidArgumentException::class, fn() => quantity(0));
assert_throws("refuses 11", InvalidArgumentException::class, fn() => quantity(11));

Since PHP 8, throw also works inside an arrow function, as in fn() => throw new OutOfStock().