setUp and tearDown
Learn the setup and teardown code that runs before and after each test with setUp() and tearDown().
What are setUp and tearDown for?
Many tests share the same setup: a new ShoppingCart, a new User. Instead of copying this code into every test, you write a setUp method. PHPUnit calls setUp automatically before each test; tearDown runs after. setUp builds shared objects (the fixture); tearDown cleans up files or database rows. This keeps tests independent and repeatable.
Test fixture
A fixture is the shared state a test needs: objects, files, database rows. setUp builds them; the test method adds its own changes on top. A good fixture is small and fast. For example, in ShoppingCartTest, setUp creates an empty cart every time; tests then check adding, removing and clearing. If tearDown is not needed, you can skip it; PHPUnit cleans up objects automatically.
Exercise Build a fixture with setUp
Make ShoppingCartTest extend TestCase. Add a setUp method that builds a new ShoppingCart before each test and stores it in the $cart property. In testStartsEmpty check the count is 0 with assertEquals. In testAddIncreasesCount add "Bread" and check the count is 1 with assertEquals.
Show example solution
void { $this->cart = new ShoppingCart(); }. In testStartsEmpty add $this->assertEquals(0, $this->cart->count()). In testAddIncreasesCount add $this->cart->add("Bread"); $this->assertEquals(1, $this->cart->count()).
Example solution:
<?php
// Here we define TestCase ourselves
class TestCase {
protected function assertEquals($expected, $actual): void {
if ($expected !== $actual) {
throw new Exception("Expected $expected, got $actual");
}
}
}
class ShoppingCart {
private array $items = [];
public function add(string $item): void { $this->items[] = $item; }
public function count(): int { return count($this->items); }
}
class ShoppingCartTest extends TestCase {
private ShoppingCart $cart;
protected function setUp(): void {
$this->cart = new ShoppingCart();
}
public function testStartsEmpty(): void {
$this->assertEquals(0, $this->cart->count());
}
public function testAddIncreasesCount(): void {
$this->cart->add("Bread");
$this->assertEquals(1, $this->cart->count());
}
}
// Run the tests
$test = new ShoppingCartTest();
$test->setUp();
$test->testStartsEmpty();
echo "testStartsEmpty: PASSED\n";
$test->setUp();
$test->testAddIncreasesCount();
echo "testAddIncreasesCount: PASSED\n";
Test yourself
-
Match the lifecycle
- setUp
- Before each test
- tearDown
- After each test
- testAdd
- Test method
- fixture
- Shared setup
-
How many times does setUp run in a test class?
- Once before all tests
- Once after each test
- Once before each test
- Only before the first test
Show answer
Once before each test — Correct. setUp runs once before each test; tests do not affect each other.
-
Complete the setUp method
<?php class CartTest extends TestCase { private ShoppingCart $cart; protected function ____(): void { $this->cart = new ShoppingCart(); } }Show answer
<?php class CartTest extends TestCase { private ShoppingCart $cart; protected function setUp(): void { $this->cart = new ShoppingCart(); } }