Test Lifecycle

Most non-trivial tests need some setup before they run — an object to test against, a database connection, sample data — and some cleanup afterward. Rather than repeating that setup code in every single test method, PHPUnit calls a handful of special methods automatically at the right points in a test class's lifecycle.

setUp() and tearDown()

setUp() runs before every single test method in the class, and tearDown() runs after every single test method. If a class has four test methods, setUp() runs four times — once immediately before each one.

MethodRunsTypical use
setUp()Before every test methodCreate a fresh object under test, open a fresh connection
tearDown()After every test methodClose connections, delete temporary files, reset global state

setUpBeforeClass() and tearDownAfterClass()

These two are different: they are static methods that run only once for the whole class — setUpBeforeClass() before any test method runs, and tearDownAfterClass() after the very last one finishes. They are the right place for expensive, one-time setup that every test in the class can safely share, such as starting a test database container or loading a large fixture file.

Worked Example

Here, setUp() creates a brand-new Calculator instance before each test method runs, storing it in a property so every test method can use $this->calculator:

<?php
use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase
{
    private Calculator $calculator;

    protected function setUp(): void
    {
        // Runs before EVERY test method - each test gets its own fresh instance
        $this->calculator = new Calculator();
    }

    public function testAddsTwoNumbers()
    {
        $this->assertEquals(5, $this->calculator->add(2, 3));
    }

    public function testSubtractsTwoNumbers()
    {
        // A completely fresh $calculator, unaffected by the previous test
        $this->assertEquals(1, $this->calculator->subtract(3, 2));
    }

    protected function tearDown(): void
    {
        // Runs after every test method - nothing to clean up for a simple Calculator
        unset($this->calculator);
    }

    public static function setUpBeforeClass(): void
    {
        // Runs ONCE before any test method in this class - good for expensive shared setup
        echo "Starting CalculatorTest suite\n";
    }

    public static function tearDownAfterClass(): void
    {
        // Runs ONCE after all test methods in this class have finished
        echo "Finished CalculatorTest suite\n";
    }
}
Note: This is real, correct PHPUnit code meant to be copied into your own project — this website's codebase has no PHPUnit installed, so it isn't executed live on this page.

Why Fresh State Per Test Matters

Because setUp() rebuilds $this->calculator before every test method, one test can never accidentally leak state into another. This matters more than it might first appear: PHPUnit does not guarantee your test methods run in the order they're written, so tests that secretly depend on state left behind by an earlier test can pass or fail depending on run order alone. Fresh state per test keeps every test method fully independent and its result reproducible no matter what order the suite runs in.

Next steps: Head to Testing Exceptions to learn how to assert that your code correctly throws an exception under bad input.