We are using Yii 1.1, but I suspect this issue would apply to anyone using PHPUnit.
Some of our unit tests depend on specific data in the database, thus we're using fixtures. Unfortunately, you define fixtures on a per-test-class basis, not a per-test-function basis.
Example:
class AccountTest extends CDbTestCase
{
public $fixtures = array(
'users' => 'User',
'email_accounts' => 'EmailAccount',
'histories' => 'History',
'email_queue' => 'EmailQueue',
'org_unit' => 'OrgUnit',
);
// ...
public function testIsValid_preventsWhiteSpaceAroundNumber()
{
// ... (test logic)...
}
// ... (more tests)...
}
Some of the tests for our Account model require several different tables to be updated to match the defined fixtures, but other tests for that same class don't depend on any fixtures at all. Unfortunately, all of the tests in our AccountTest.php file (which contains the tests for our Account model) have the added delay of reloading the fixtures for those five tables in the database.
As a specific example, the Account->isValid()
function now has seven unit tests to confirm various things about what it does or doesn't consider valid. I did a test of running the testIsValid
unit tests with and without fixtures (which those tests don't need): with fixtures took 2.95 seconds, without took 0.068 seconds.
We have already tried (in an attempt to solve a different problem) creating two different AccountTest.php files (in different folders) to separate out our unit tests into different groups, but that caused more problems than it resolved.
My ultimate goal is to be able to define for a particular test whether it needs any database fixtures loaded (and if so, which ones) so that the tests which don't depend on fixtures can run much faster, without the delay of waiting for the database to be (unnecessarily) updated.
Thus my question: Is there a way to only load specific fixtures for a given PHPUnit test?
How about this? Assuming your test class extends \CDbTestCase ...
add the following ...
public function loadFixtures($fixtures=null)
{
if ($fixtures === null) {
$fixtures = $this->optionalFixtures;
}
if(is_array($fixtures))
$this->getFixtureManager()->load($fixtures);
$this->fixtures = $fixtures;
}
Then, in all the test where you want (the) fixtures loaded, add a call to that method (with an optional array). Tests without that call should end up running without the fixtures getting loaded, although fixtures may still be in the database from previous tests.