TDD with Zend Framework

  • Part 1 – Getting Started
  • Part 2 – Testing Controllers
  • Part 3 – Mocks and Stubs
  • Part 4 – Wrapping up the controller
    • Jani Hartikainen has an interesting unit testing series on his blog where he introduces and expands on unit testing php code with phpunit. It’s a really good read and it pushed me to add his feed to my reader so I could stop going to the site daily to check for updates.

      However, as useful as the series is, it doesn’t provide answers to Zend Framework specific testing issues (and considering all the ZF-specific posts on his site, that’s quite surprising). It is also aimed at beginner programmers. Most of the programmers I work with don’t need to know what a unit test or an assertion is. They need to know how to test ZF controllers and models and I was sort of hoping I could just point them at the series.

      In the coming weeks, I’ll put together a how-to on testing ZF applications using a Test Driven Development (TDD) approach. With TDD tests are written first and as such the test suite guides the design of the production code. Uncle Bob has a rather intriguing article where he summarises TDD into three ‘simple’ rules:

      • No production unless there’s a failing test
      • Write no more of a unit test than is sufficient to fail
      • Write no more production code than is sufficient to pass the failing test

      In this series, I will attempt to build a mini-application using TDD and the Zend Framework.

      The mini app

      I have chosen to build a newsletter subscription form as a test app. It’s simple enough to not distract from the primary aim of the exercise while providing a cause to test the entire MVC stack as well as the sending of emails.

      The mini-app will have relatively simple requirements:

      • As a user, I want to visit the home page and see a form where I can enter my full name and email address.
      • As a user, I should be shown the form to try submitting my details again when I submit invalid details.

        • The fullname field is required, should be at least 2 characters long and contain only alphanumeric characters and spaces.
        • The email field is required and should be a valid email address.
      • As a user, I should be redirected to a thank you page when I submit valid details.

        • The submitted (and validated) details should be saved to the database.
      • As a user, I should get a confirmation email to complete my subscription.

      Setting up

      I am going to assume a fresh Zend Framework 1.9 application with the test files already setup. I found this Zend Framework 1.8 with Zend_Application and PHPUnit walk-through quite helpful.
      Alternatively, download a copy of Jara Base either from GitHub or as a zipped file.

      I will also assume some level of comfort with the Zend Framework. If not, the afore-mention Quick Start and Akra’s ZF 1.9 tutorial should come in handy.
      I will be using the trial version of Zend Studio 7 for this so I can test it out (need to know if it’s worth upgrading). I have this set up on my laptop running windows XP not my regular dev box (running Ubuntu) and I had the following issues while setting up PHPunit and Zend Framework on Windows. Hopefully my fixes will help someone.

      • I got a ‘Cannot redeclare class Zend_Openid_Provider’ when trying to run Zend_Tool. I had to remove a duplicate copy of the Zend Framework library.
      • I also got ‘Warning (Phpunit_Framework_Warning) No tests found in file …’. Short tags were disabled in CLI php.ini file and the file had short tags in it.
      • Php was not in my path. Had to add it.
      • I had old version of pear(1.5.4) and to upgrade, I had to uninstall it first.
      • Installing mysgit gave me a nice bash console on windows.

      I also tested this out on a fresh ubuntu install (9.04) and got the following error while trying to install PHPUnit:

      Did not download optional dependencies: pear/Image_GraphViz, pear/Log, use --alldeps to download automatically
      phpunit/PHPUnit requires PEAR Installer (version >= 1.8.1), installed version is 1.7.1
      phpunit/PHPUnit can optionally use package "pear/Image_GraphViz" (version >= 1.2.1)
      phpunit/PHPUnit can optionally use package "pear/Log"
      phpunit/PHPUnit can optionally use PHP extension "xdebug" (version >= 2.0.0)
      No valid packages found
      install failed
      

      To fix that, upgrade pear with: sudo pear upgrade-all and the error goes away.

      Getting started

      Jara Base already has the unit testing framework setup and includes tests for the Home page and about pages so I’ll just use that.
      Zend Framework has no set way of setting tests up so I’ve used what I’m most comfortable with – which is a blend of the setup in the ZendCasts unit testing tutorial, the Ruby on Rails test setup and the test setup in the Quick Start example application.
      My setup includes a TestHelper file and the first part of this file (as shown below) is almost a copy of the application index.php file. The differences are that the APPLICATION_ENV constant is set to ‘test’ and Zend Application isn’t included.
      The next bit is an abstract BaseControllerTestCase class and all controller tests should extend this class. Only the controller tests need Zend_Application and so the bootstraping is done in there.

      <?php
      set_include_path(implode(PATH_SEPARATOR, array(
          realpath(dirname(__FILE__) . '/../library'),
          get_include_path(),
      )));
      
      define('APPLICATION_ENV', 'test');
      defined('APPLICATION_PATH')
          || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
      
      require_once 'Zend/Loader/Autoloader.php';
      $autoloader = Zend_Loader_Autoloader::getInstance();
      
      /**
       * Base Controller Test Class
       *
       * All controller test should extend this
       */
      abstract class BaseControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase {
      
          public function setUp() {
              $application = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini');
              $this->bootstrap = array($application->getBootstrap(), 'bootstrap');
              return parent::setUp();
          }
      
          public function tearDown() {
              /* Tear Down Routine */
          }
      }
      

      To confirm everything’s setup properly I’ll open up a console and navigate to the tests folder in the application root.
      Running the ‘phpunit’ command should give me passing tests (using Jara Base). To follow along, the tests can be deleted so we start with a blank slate.

      There are two main school of thoughts regarding where to start when it comes to TDD and web apps – domain logic first or interface first.
      They both have their pros and cons but in my opinion starting the models first encourages functional testing and not unit testing (in the real sense of it) since the the models are already working by the time you get to testing the controllers.

      I will go the interface first route and the next part starts off with testing controllers (and bits of the view).

      Related posts:

      1. Zend Framework – my three month review
      2. Jara Base – a base Zend Framework app
      3. Jazz up your phpunit test results
This entry was posted in Zend Framework. Bookmark the permalink.

12 Responses to TDD with Zend Framework

  1. Pingback: Avnet Labs Blog: TDD with Zend Framework | Webs Developer

  2. Hi,

    I’m very much involved in unit testing of zf applications and as a coincidence I posted yesterday a quick tutorial on setting up Zend Framework for unit testing (see my blog).

    When I look at your last paragraph, where you mention not to use Zend_Application, I’m fearing you’re going to end up in trouble when upgrading your application with the latest Zend Framework library.

    I’m not criticizing your approach, but as I found out myself the hard way, keeping options open for future releases is often a good choice.

    Since you’re making a series, it won’t harm to present both options.

    Anyways, I’m looking forward reading more about it, because I might learn some new tricks.

    Keep up the good work and have phpun !

    Michelangelo

  3. Starting TDD from the controllers is a bit strange I think, especially in Zend Framework where they should be thin as injecting collaborators is prone to errors. :)

  4. Ekerete says:

    @Michelangelo,
    I am using Zend_Application. In the last code snippet (the TestHelper file), I create an abstract base controller test class and use Zend_Application in the setup routine.
    The model tests don’t need it so we can save ourselves the overhead.

    @Giorgio,
    I tend to build my apps interface-first. It does involve a fair bit of mocking and stubbing but we’re jumping the gun here :) . I look forward to different perspectives throughout this series.

  5. Jonathan says:

    Thank you so much for taking the time to put this together. I really want to learn how to do this well. I will be sharing this with others that I work with.

  6. Pingback: Zend Framework University — Blog — AvnetLabs Blog: TDD with Zend Framework

  7. Pingback: Zend Framework Blog » Blog Archive » Aus den Zend Framework Blogs

  8. Pingback: Zend Framework – mega zestawienie « W drodze ku szczęściu

  9. Pingback: TDD mit Zend · Infoblog

  10. Pingback: blog.nielslange.de » Test Driven Development (TTD) with the Zend Framework

  11. Pingback: Zend Framework – INICIO « Oscar Viana's Weblog

  12. Interesting! This is exactly what I was looking for!

    Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>