- Part 1 – Getting Started
- Part 2 – Testing Controllers
- Part 3 – Mocks and Stubs
- Part 4 – Wrapping up the controller
- 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
- 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.
- 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.
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:
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:
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 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:
Pingback: Avnet Labs Blog: TDD with Zend Framework | Webs Developer
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
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.
@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 look forward to different perspectives throughout this series.
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
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.
Pingback: Zend Framework University — Blog — AvnetLabs Blog: TDD with Zend Framework
Pingback: Zend Framework Blog » Blog Archive » Aus den Zend Framework Blogs
Pingback: Zend Framework – mega zestawienie « W drodze ku szczęściu
Pingback: TDD mit Zend · Infoblog
Pingback: blog.nielslange.de » Test Driven Development (TTD) with the Zend Framework
Pingback: Zend Framework – INICIO « Oscar Viana's Weblog
Interesting! This is exactly what I was looking for!
Thanks!