I am trying to learn Unit Testing using Zend Framework. I have set up a test application called LyZend in Github. Supposedly, the application should be able to display artists, albums, and tracks.
The tests are found in: http://github.com/wenbert/lyzend/tree/master/tests/ I have follwed Matthew Weier O’phinney’s method of setting up the tests.
lyzend / tests / TestHelper.php
<?php require_once 'TestConfig.php'; /* * Start output buffering */ ob_start(); /* * Set error reporting to the level to which Zend Framework code must comply. */ error_reporting( E_ALL | E_STRICT ); /* * Set default timezone */ date_default_timezone_set('GMT'); /* * Determine the root, library, tests, and models directories */ $root = realpath(dirname(__FILE__) . '/../'); $library = $root . '/library'; $tests = $root . '/tests'; $models = $root . '/application/models'; $controllers = $root . '/application/controllers'; /* * Prepend the library/, tests/, and models/ directories to the * include_path. This allows the tests to run out of the box. */ $path = array( $models, $library, $tests, get_include_path() ); set_include_path(implode(PATH_SEPARATOR, $path)); /** * Register autoloader */ require_once 'Zend/Loader/Autoloader.php'; //Zend_Loader::registerAutoload(); Zend_Loader_Autoloader::getInstance(); /* * Add library/ and models/ directory to the PHPUnit code coverage * whitelist. This has the effect that only production code source files appear * in the code coverage report and that all production code source files, even * those that are not covered by a test yet, are processed. */ if (defined('TESTS_GENERATE_REPORT') && TESTS_GENERATE_REPORT === true && version_compare(PHPUnit_Runner_Version::id(), '3.1.6', '>=')) { PHPUnit_Util_Filter::addDirectoryToWhitelist($library); PHPUnit_Util_Filter::addDirectoryToWhitelist($models); PHPUnit_Util_Filter::addDirectoryToWhitelist($controllers); } /** * Setup default DB adapter */ /* $db = Zend_Db::factory('pdo_sqlite', array( 'dbname' => $root . '/data/db/bugs.db', )); Zend_Db_Table_Abstract::setDefaultAdapter($db); */ /* * Unset global variables that are no longer needed. */ unset($root, $library, $models, $controllers, $tests, $path); |
You might noticed that I included a TestConfig.php file above. Here is the file:
<?php // Define path to application directory defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application')); // Define application environment defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'testing')); // Ensure library/ is on include_path set_include_path(implode(PATH_SEPARATOR, array( realpath(APPLICATION_PATH . '/../library'), get_include_path(), ))); |
Here is a sample test for my Artist Model.
lyzend / tests / application / models / ArtistTest.php
<?php // Call Model_ArtistTest::main() if this source file is executed directly. if (!defined("PHPUnit_MAIN_METHOD")) { define("PHPUnit_MAIN_METHOD", "Model_ArtistTest::main"); } require_once dirname(__FILE__) . '/../../TestHelper.php'; /** Model_Artist */ require_once 'Artist.php'; require_once 'ArtistMapper.php'; require_once 'DbTable/Artist.php'; /** * Test class for Model_Artist. * * @group Models */ class Model_ArtistTest extends Zend_Test_PHPUnit_ControllerTestCase { /** * Runs the test methods of this class. * * @return void */ public static function main() { $suite = new PHPUnit_Framework_TestSuite("Model_ArtistTest"); $result = PHPUnit_TextUI_TestRunner::run($suite); } /** * Sets up the fixture, for example, open a network connection. * This method is called before a test is executed. * * @return void */ public function setUp() { $this->bootstrap = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . DIRECTORY_SEPARATOR . 'configs' . DIRECTORY_SEPARATOR . 'application.ini' ); parent::setUp(); } /** * Tears down the fixture, for example, close a network connection. * This method is called after a test is executed. * * @return void */ public function tearDown() { } public function testCanTest() { //this is a sample test } } |
The XML file is like this:
<phpunit> <testsuite name="Ly Test Suite"> <directory>./</directory> </testsuite> <php> <!-- <ini name="include_path" value="../library"/> --> </php> <filter> <whitelist> <directory suffix=".php">../library/</directory> <directory suffix=".php">../application/</directory> <exclude> <directory suffix=".phtml">../application/</directory> <file>../application/Bootstrap.php</file> <file>../application/controllers/ErrorController.php</file> </exclude> </whitelist> </filter> <logging> <log type="coverage-html" target="./log/report" charset="UTF-8" yui="true" highlight="true" lowUpperBound="50" highLowerBound="80"/> <log type="testdox-html" target="./log/testdox.html" /> </logging> </phpunit> |
Running the test would be something like this:
phpunit --configuration phpunit.xml
Matthew did not provide sample test for Mappers. So I created one something like this:
$mapper = new Ly_Model_ArtistMapper(); $this->assertTrue($mapper instanceof Ly_Model_ArtistMapper); |
My process was like:
- Setup Unit Testing in Zend Framework
- Create tests (let’s say for Artist Model).
- Make code in my model to pass the tests.
- Repeat step 2 and then go to next model if satisfied.
FYI: I am not so sure about my Model. I am not sure if I am breaking any rules when I created them. It would be cool if you could check them out (http://github.com/wenbert/lyzend/tree/master/application/models/) and discuss my mistakes below.
Thanks!