views:

1290

answers:

3

Has anyone had any success setting up Zend_Test? What was your method/approach and how do you run your tests/test suites?

I already have PHPUnit installed and working. Now I'm trying to write some simple controller tests. The Zend Framework documentation assumes that autoloading is setup, which I haven't done. What method do you use to autoload the appropriate files? I do so in my normal bootstrap file, but I don't want to clutter up my Test with a bunch of includes and setting up paths. Would an abstract controller test case class be the way to go?

What about the bootstrap plugin like the documentation uses...is that how you bootstrap your tests, or do you like to do it a different way? I would like to re-use as much of the regular bootstrap file as I can. How should I DRY up my bootstrap for testing and normal use?

Here's my test so far:

<?php

class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
    public function setUp()
    {
        $this->bootstrap = array($this, 'appBootstrap');
        parent::setUp();
    }

    public function appBootstrap()
    {
        $this->frontController->registerPlugin(new Bootstrapper('testing'));
    }

    public function testIndexAction()
    {
        $this->dispatch('/index');
            $this->assertController('index');
            $this->assertAction('index');
    }

}

//straight from the documentation
class Bootstrapper extends Zend_Controller_Plugin_Abstract
{
    /**
     * @var Zend_Config
     */
    protected static $_config;

    /**
     * @var string Current environment
     */
    protected $_env;

    /**
     * @var Zend_Controller_Front
     */
    protected $_front;

    /**
     * @var string Path to application root
     */
    protected $_root;

    /**
     * Constructor
     *
     * Initialize environment, root path, and configuration.
     *
     * @param  string $env
     * @param  string|null $root
     * @return void
     */
    public function __construct($env, $root = null)
    {
        $this->_setEnv($env);
        if (null === $root) {
            $root = realpath(dirname(__FILE__) . '/../../../');
        }
        $this->_root = $root;

        $this->initPhpConfig();

        $this->_front = Zend_Controller_Front::getInstance();
    }

    /**
     * Route startup
     *
     * @return void
     */
    public function routeStartup(Zend_Controller_Request_Abstract $request)
    {
        $this->initDb();
        $this->initHelpers();
        $this->initView();
        $this->initPlugins();
        $this->initRoutes();
        $this->initControllers();
    }

    // definition of methods would follow...
}

What should I do?

A: 

I always use a simple TestHelper.php that does some basic initialization stuff. This file is included in every test-case file. One of the things I do, is registering the Zend Framework autoloader as I experienced major dependency problems especially when using filters, validators and forms. It's nearly impossible to keep track of all the required files and include them manually in the test-cases.

You can perhaps move the autoloading initialization and the setup of the include paths into your bootstrapping plugin as this procedure should be the same for the real application.

Stefan Gehrig
+1  A: 

Here's what I did to get it to work:

First, we need to resolve the autoloading issue. We'll do this by creating a file that all the tests will include, and put it in the tests directory. Note: I pretty much copied all of this from my /public/index.php.

# /tests/loader.php

<?php

define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application/'));

set_include_path( APPLICATION_PATH . '/../library' . PATH_SEPARATOR .
         APPLICATION_PATH . '/models' . PATH_SEPARATOR .
         APPLICATION_PATH . '/forms' . PATH_SEPARATOR .
         get_include_path() );

require_once "Zend/Loader.php";
Zend_Loader::registerAutoload();

Second, we need to include this file in our test. Our test file is in /tests/application/controllers/ . I'm not going to use my bootstrap as a plugin since my bootstrap file works the same way as the QuickStart tutorial. I'll just link to it by setting the location as the public $bootstrap. When Zend_Test_PHPUnit_ControllerTestCase constructs, it will look for the bootstrap file that we set here.

<?php

require_once '../../loader.php';

class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
{
    public $bootstrap = '../../../application/bootstrap.php';

    public function testIndexAction()
    {
     $this->dispatch('/index');
        $this->assertController('index');
        $this->assertAction('index');
    }

}

And that's it! If my bootstrap file was already a plugin, this might be a little more complicated, but since it's not, it's super easy.

Andrew
+1  A: 

Instead of using

require_once "Zend/Loader.php";
Zend_Loader::registerAutoload();

change it into

require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance();

registerAutoLoad() is deprecated as of 1.8.0

bhoo-day