dc

Zend Framework 1.11 + PHPUnit 3.6 unit testing

At work we are up to date with PHPUnit  at 3.6, yet officially ZF1 will only support PHPUnit 3.4. Looking through the code there is some support for PHPUnit 3.5, but I actually make use of the additional assertions that PHPUnit 3.6 provides. Initially I had intended on just extending the Zend_Test PHPUnit classes but I quickly ran into the problem where the ZF classes didn’t implement methods in the interfaces when they were brought into the PHP interpreter. I then thought about copying over the Zend_Test classes and renaming them, this would have created a maintenance issue since we don’t want to maintain our own fork of the Zend_Test classes.

My final solution was simply to create my own DatabaseTestCase. This is what I came up with:

/**
 * Generic TestCase for PHPUnit 3.6 Database testing with Zend Framework 1.11
 *
 * @author  David Lundgren
 * @license MIT license <http://opensource.org/licenses/MIT>
 * @package zf+phpunit-tests
 */
abstract class App_Test_PHPUnit_DatabaseTestCase
	extends PHPUnit_Extensions_Database_TestCase
{
	/**
	 * Convenience function to get access to the database connection.
	 *
	 * @return PHPUnit_Extensions_Database_DB_IDatabaseConnection
	 */
	public function getConnection()
	{
		$adapter = Zend_Db_Table::getDefaultAdapter();
		$config  = $adapter->getConfig();
		return $this->createDefaultDBConnection($adapter->getConnection(), $config['dbname']);
	}

	/**
	 * Convenience function to create a QueryDataSet
	 *
	 * @param  string $table
	 * @param  string $query
	 * @return PHPUnit_Extensions_Database_DataSet_QueryDataSet
	 */
	public function getQueryDataSet($table, $query = null)
	{
		$ds = new PHPUnit_Extensions_Database_DataSet_QueryDataSet($this->getConnection());
		$ds->addTable($table, $query);
		return $ds;
	}

	/**
	 * Returns the database operation executed in test cleanup.
	 *
	 * @return PHPUnit_Extensions_Database_Operation_DatabaseOperation
	 */
	protected function getTearDownOperation()
	{
		return PHPUnit_Extensions_Database_Operation_Factory::NONE();
	}
}

Before I started using the Zend_Test classes I had App_Test_Helper for handling some static calls, this also had truncateTable, loadSqlFile, and a few other methods to help with testing. This actually reduces it down to creating an ArrayDataSet (to setup the fixtures in the test, which allows null values), and then using something like the following

class App_Test_SomeTests
	extends App_Test_PHPUnit_DatabaseTestCase
{
	private $defaultRows = array(array(...), array(...));
	private $testRow = array(...);
	...
	public function testTableDataSet()
	{
		...
		$rows   = $this->defaultRows;
		$rows[] = $this->testRow;
		$this->assertDataSetsEqual(
			new App_Test_PHPUnit_Db_DataSet_ArrayDataSet(array('table' => $rows)),
			$this->getQueryDataSet('table')
		);
		...
	}
	...
}

I didn’t have to rewrite all of my tests due to no longer using Zend_Test_PHPUnit_DatabaseTestCase and it the tests pass/fail as they should.

UPDATE: Added a license clause to the code.

Leave a reply