Pádraic Brady

PHP, Zend Framework and Other Crazy Stuff

The PHPSpec Zend Framework App Testing Manifesto: ZF Integration

Jan 17th

Posted by Pádraic Brady in PHP General

View Comments

In the Preamble to this Manifesto, I set out the basic proposal for direct integration of support for applying Behaviour-Driven Development (BDD) to the Zend Framework. The ideal was to move away from line-by-line setup and manipulation of Zend instances towards a more simplified model which is standardised for any PHPSpec specs.

This morning I merged the experimental branch for the implementation of the Zend Framework specific PHPSpec_Context into the main trunk for release in PHPSpec 0.3.0. Documentation of the Zend Context will be completed within the next day or two and added to the growing PHPSpec Manual at http://dev.phpspec.org/manual now available.

The main customisation required to get the Zend Context operational is to set up elements of the FrontController, I’ve selected two primary methods. The first is to use several static methods on PHPSpec_Context_Zend (addControllerDirectory() and addModuleDirectory()) and a more flexible addFrontControllerSetupCallback() which will accept a custom function or static method reference to execute. The former is handy since you can easily organise your bootstrap file into a static class and segregate FrontController, Dispatcher, Action Helper, etc. elements you are using to customise how the Zend Framework operates. Both can be called from any file included into a Context file (e.g. SpecHelper.php).

Here’s a really simple example of a Zend Framework spec. I’ll post a more in-depth tutorial next week once the Manual is finalised, and some final cleanups applied (e.g. allowing for Router specification). The only priority for basic operations left is an implementation of a Zend_Factory class to allow you to replace objects directly instantiated within controllers (to maintain the golden standard of specifying/testing controllers isolated from it’s dependencies). We’ll really start kicking some ZF ass when PHPMock has an initial devel release!

[geshi lang=php]PHPSpec_Context_Zend::addControllerDirectory(‘../src/application/controllers’);

class DescribeTwitterController extends PHPSpec_Context_Zend
{

public function itShouldDisplayHomeTweetsFromDefaultRetrieveAction()
{
$this->get(‘retrieve’);
$this->response()->should->haveText(‘Tweets From Twitterers Followed:’);
}

public function itShouldPostTweetOnSendActionUsingPostData()
{
$this->post(‘send’, array(‘message’=>’@padraicb: All your specs are belong to us’));
$this->response()->should->haveText(‘You submitted a new Tweet!’);
}

public function itShouldRetrieveMessagesForUserIdInParamsFromRetrieveAction()
{
$this->get(‘twitter/retrieve/user/padraicb’);
$this->response()->should->beSuccess();
}
}[/geshi]

It’s obvious this is bare minimum. There is still a lot of ground to cover incl. integrating PHPMock, so you can literally mock/stub the Twitter service package being used in the controller action itself (Note to Matthew – implement Zend_Service_Twitter already…;)) and set expectations of how the Controller should use that Twitter service. Adding some basic HTML/XML safe Matchers would also add some fairly substantial help for specifying what the response output should be, or what template any controller action should render.

But the basics, and in short the most time consuming, bit of integration to get something working with the Zend Framework at a level not requiring any devious workarounds is now complete. The weekend should see some really useful additions to this base. Your comments are most welcome as usual whether here, or on the mailing list.

bdd, behavior-driven development, behaviour-driven development, php, php general, php security, phpmock, phpspec, tdd, unit testing, zend framework, zf proposal

The PHPSpec Zend Framework App Testing Manifesto: Preamble

Jan 11th

Posted by Pádraic Brady in PHP General

View Comments

(…or some title designed to attract curious readers so I can captivate them into thinking this will not be a long torturous blog entry)

Over the course of the next obsessional phase I go through I’ll be attempting to pound the Zend Framework into submission so I can apply Behaviour-Driven Development (BDD) using PHPSpec when I write a Controller. Why? Because I feel like it, and it gives me an excuse to promote one possible incarnation of PHPMock and the PHPSpec Zend Framework extension. See? Perfectly reasonable selfishness!

The other reason is that whether you apply TDD, or the funky new presence of BDD in PHP, applying some form of predictive specification before you rush into PHPEclipse to start typing PHP is a good thing. The alternative is long nights debugging why Controller X and Model Y refuse to produce View Z. The immediate problem with this is that the Zend Framework currently does not offer some means of manipulating Framework operations with a simplified API, instead you have to muck about with Zend_Controller_Front and all sorts of other long-winded-named classes whose operation is often mysterious if you’ve managed to evade tinkering with them while building the Universe’s next greatest social networking site.

Never fear, there are established solutions. One of the easiest to find is archived on the fw-general mailing list for the framework, a relatively straightforward post by the Master Of MVC Operations, Matthew Weier O’Phinney, using PHPUnit and an extended PHPUnit_TestCase class. Here’s the URL in case you missed it:
How to use PHPUnit in a MVC project

For PHPSpec I hope to simplify even further. Moving from Zend_Controller_*::someConfusingMethod() x 5 to PHPSpec_Context::doItAlreadyOrIllKillSomething(). The basis of this theoretical (unless you’ve found the top secret location of the subversion repo) discussion is that simple is better, and easier is way better still. To get there one needs to compact Zend Framework operations into a handful of easy to remember methods and practices. Unfortunately it does also require some Zend Framework fun by establishing a few ground rules on how you write Controller code. We’ll get there much later, because it’s one detail not necessary to cover in an opening sortie and it’s not incredibly troublesome (I think).

To refresh your memory, PHPSpec as a BDD framework is designed to kick your ass into high-TDD gear without needing 2+ years of prior experience to get there. It’s also designed to aid your thought approach by using a readable API. Besides being easy to learn, it also enforces several well-established best practices in TDD and xUnit Patterns. Here’s a quickie shot:

[geshi lang=php]class DescribeZendFramework extends PHPSpec_Context {

public function itShouldMakeWebDevelopmentBetter() {
$zend = new Zend_Framework;
$this->spec($zend->isBetter())->should->beTrue();
}
}[/geshi]
Stored as ZendFrameworkSpec.php, you could run this spec by hitting it’s location on the command line (there is a HTML Runner option) and running:

phpspec ZendFrameworkSpec

Not rocket science. Back to the topic of applying BDD… If one thinks a bit, any ZF request is composed of only a few key components. There’s the Request (POST/GET/COOKIE/URI Params), the Controller, the Action on the Controller, and finally the Response. In between are bits and pieces which while important in a complex application we needn’t dwell on yet.

In a perfect world, we could wave a magic wand and drop big hints like:

[geshi lang=php]class DescribeIndexController extends PHPSpec_Context_Zend
{

public function itShouldDisplayHelloWorldOnIndexAction()
{
$this->get(‘index’);
$this->response()->should->match(“/Hello World/”);
}
}[/geshi]
The basic foundation above is simple enough. The Controller is derived from the class name, the Action is passed to the relevant request method (get() for GET), there’s a response upon which specifications can be defined.

In an inperfect world, it’s not quite as simple as this. In applying TDD or BDD a big annoyance is ensuring we only test isolated specifics. In a typical Controller Action one can easily expect a few things:

1. Models
2. Misc Objects (e.g. Zend_Mail)
3. View Rendering

The biggest problem in there are Models. Models are incredibly irritating objects that insist on writing to databases. They are also as common as dirt in Controllers. Not exactly good company when applying TDD or BDD. The suggested best practice approach is to Mock or Stub these demons out of their evil ways, and turn them into predictable automatons (we can separately spec/test the actual Model classes independently). In other words, we need to Mock/Stub the dependencies of the class being tested/spec’d so it’s isolated – should sound familiar as an intonation of Unit Testing practitioners worldwide.

That’s the problem in a nutshell. Controllers tend to directly instantiate new objects without the benefit of good Dependency Injection. Makes them very difficult to test discretely without falling back on the double-edged sword of pure functional or acceptance testing. And that double-edged sword is quite popular in PHP right now.

Enter something like a Factory. Using a Factory, our specs/tests can potentially intercept objects used in a Controller and replace them with Mocked or Stubbed copies whose behaviour is controller by us. The simplest style would be to use a general object Factory to replace both require_once and new keywords (i.e. introduce a new Controller convention whereby we don’t use the “new” keyword if avoidable in Action code). Something whose API is similar to:

[geshi lang=php]$mailer = Zend_Factory::create(‘Zend_Mail’);[/geshi]
A suitable Zend_Factory class would inherently know the require path for Zend_Mail, and would return a new Zend_Mail object (assume optional constructor params in the API are supported). Couple this with some backend Registry and one could allow PHPSpec/PHPUnit to play god with:

[geshi lang=php]Zend_Factory::replaceClass(‘Zend_Mail’, new Zend_Mail_Mocked);[/geshi]
Now any call to Zend_Factory::create(‘Zend_Mail’) would actually return a registered Mock of Zend_Mail. Granted the API ignores multiple objects and non-Zend classes for now (an API potential discussion for another day if this goes beyond theory) but you get the point. Replacing “new Class” with “Zend_Factory::create(‘Class’)” in a Controller Action would facilitate mocking by introducing a healthy dose of Dependency Injection. Let’s kick another example using PHPSpec and PHPMock (note: PHPMock is undergoing development so the API is questionable as to its stability) where the PHPSpec_Context_Zend extension defines additional helper methods on top of the normal ones attached to PHPSpec_Context. This is suppossed to be the revelationary part of the blog post so pay attention and critique it to death in the comments.

[geshi lang=php]require_once ‘Zend/Mail.php’;

class DescribeIndexController extends PHPSpec_Context_Zend
{

public function before()
{
$this->mail = phpmock(‘Zend_Mail’);
$this->replaceClass(‘Zend_Mail’, $this->mail);
}

public function itShouldSendAnEmailUsingPostData()
{
// setup the Mocked Zend_Mail instance (no real email sent of course)
$this->mail->shouldReceive(‘setBodyText’)->with(‘This was a test email’)->once();
$this->mail->shouldReceive(‘setFrom’)->with(‘anon@example.net’)->once();
$this->mail->shouldReceive(‘setTo’)->with(‘padraic@example.com’)->once();
$this->mail->shouldReceive(‘setSubject’)->with(‘Testing…1…2…3′)->once();
$this->mail->shouldReceive(‘send’)->withNoArgs()->once();

// POST request to IndexController::mailAction()
$this->post(
‘mail’,
array(
‘email’=>’padraic@example.com’,
‘subject’=>’Testing…1…2…3′,
‘body’=>’This was a test email’
)
);

// and because no PHPMock integration with PHPSpec yet…ugly append
$this->spec($this->mail->verify())->should->beTrue();

// we’re ignoring the Response for now..oh ok then
$this->response()->should->beSuccess();
$this->response()->should->match(“/successfully sent/”);
}
}[/geshi]
Screw “new Zend_Mail”, let’s mock the divil ‘imself mo chara! What works for Zend_Mail would feasibly also work for Models. So in theory (at a personal perspective) I like my Manifesto Preamble. Having a simplified approach to applying BDD or TDD to Zend Framework controllers (someone else can take on Symfony if they wish) is something I’d very much like to have.

Now we have no implementation, just a BDD derived specification of what the future implementation should do once complete. To round off the example, here’s a possible implementation:

[geshi lang=php]class IndexController extends Zend_Controller_Action
{

public function mailAction()
{
// ignore security for brevity; normally we’d be damned sure $post
// was the result of filtered/validated data
$post = $_POST;

$mailer = Zend_Factory::create(‘Zend_Mail’); // presto; delivers PHPSpec defined Mock
$mailer->setBodyText($post['body']);
$mailer->setFrom(‘anon@example.net’);
$mailer->setTo($post['email']);
$mailer->setSubject($post['subject']);
$mailer->send();

$this->getResponse()->setBody(‘Email successfully sent.’);
}
}[/geshi]
Of course this is total drivel without a) a stable PHPMock, and b) PHPSpec_Context_Zend. I’ll take a quick proof-of-concept stab later after I investigate the wonders of GIT to see if it kicks SVK up the rear… In the meantime is this drivel for real, or does it have potential? Commentors who use the phrase “Mad Irishman” will be booted…

More when the PHPSpec 0.3.0 branch is active.

bdd, behaviour-driven development, mock objects, php, php general, php security, phpmock, phpspec, tdd, unit testing, zend framework
« First...304050«5859606162»708090...Last »
  • Recent Activity

    • Publishing Security Disclosures In Consumable Formats For Simpler Aggregation and Security Checking
    • 20 Point List For Preventing Cross-Site Scripting In PHP
    • Mockery 0.8.0 Has Been Unleashed!
    • Predicting Random Numbers In PHP – It’s Easier Than You Think!
    • Getting Ahead In Security By Watching The Neighbours
  • My latest tweets

    Loading tweets...
    Follow me on Twitter!
  • Recent Comments

    • JackLee on Publishing Security Disclosures In Consumable Formats For Simpler Aggregation and Security Checking
    • Ashraf Mansour on Publishing Security Disclosures In Consumable Formats For Simpler Aggregation and Security Checking
    • Kraftsmann on Publishing Security Disclosures In Consumable Formats For Simpler Aggregation and Security Checking
    • Anonymous on Mockery 0.6.1 Released
    • Emmanuel Art on Publishing Security Disclosures In Consumable Formats For Simpler Aggregation and Security Checking
  • Calender

    June 2013
    M T W T F S S
    « May    
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
  • Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported
    This work by Pádraic Brady is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported.
  • Tags

    application security article astrum futura atom bdd behavior-driven development behaviour-driven development book Cross-Site Scripting dependency injection design patterns htmlpurifier irishisms maugrim mockery mock objects mutation testing mvc oauth openid openid and yadis pc gaming pear php php game development php general phpmock php security phpspec phpunit qgl quantum star se rantings rss surviving the deep end tdd tutorial unit testing xp programming xss yadis yaml zend framework zf proposal zfstde
  • Categories

    • Astrum Futura
    • Irishisms
    • Openid and Yadis
    • PC Gaming
    • PHP Game Development
    • PHP General
    • PHP Security
    • Quantum Star SE
    • Zend Framework
  • Archives

    • May 2013
    • April 2013
    • March 2013
    • January 2013
    • October 2012
    • September 2012
    • August 2012
    • June 2012
    • April 2012
    • March 2012
    • January 2012
    • October 2011
    • August 2011
    • July 2011
    • June 2011
    • May 2011
    • April 2011
    • March 2011
    • February 2011
    • October 2010
    • September 2010
    • August 2010
    • July 2010
    • June 2010
    • May 2010
    • February 2010
    • October 2009
    • September 2009
    • August 2009
    • July 2009
    • June 2009
    • April 2009
    • March 2009
    • February 2009
    • January 2009
    • December 2008
    • November 2008
    • October 2008
    • May 2008
    • April 2008
    • March 2008
    • February 2008
    • January 2008
    • December 2007
    • November 2007
    • October 2007
    • September 2007
    • July 2007
    • June 2007
    • May 2007
    • April 2007
    • March 2007
    • February 2007
    • January 2007
    • December 2006
    • November 2006
    • October 2006
    • September 2006
    • August 2006
    • July 2006
    • June 2006
    • May 2006
    • April 2006
    • March 2006
    • February 2006
    • January 2006
    • December 2005
    • November 2005
    • October 2005
    • September 2005
    • August 2005
    • June 2005
    • May 2005
    • April 2005
    • March 2005
    • February 2005
    • January 2005
    • November 2004
    • October 2004
    • September 2004
    • July 2004
    • June 2004
    • May 2004
  • Meta

    • Log in
    • Entries RSS
    • Comments RSS
    • WordPress.org
Mystique theme by digitalnature | Powered by WordPress
RSS Feeds XHTML 1.1 Top
Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported
This work by Pádraic Brady is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported.