Resetting the database between tests by truncating every table is correct and slow, and it re-runs the seed data on each one. Wrapping each test in a transaction and rolling back is the same isolation for a fraction of the cost.
public function setUp()
{
parent::setUp();
$this->db->beginTransaction();
}
public function tearDown()
{
$this->db->rollBack();
parent::tearDown();
}
Two things break it. Code under test that commits its own transaction ends yours, and everything after leaks — MySQL has no true nesting, so a savepoint-based helper is needed if the code uses transactions itself. And DDL is implicitly committed, so a test that creates a table cannot be rolled back. Both are worth knowing before spending an afternoon on a test that pollutes the next one.