Unit testing Zend Framework Applications
Moderator: General Moderators
Unit testing Zend Framework Applications
I was asking around on the #zftalk irc channel about unit testing zend framework applications and was told to check out this proposal: http://framework.zend.com/wiki/display/ ... astructure
Although I'm very excited that there is talk of including unit testing functionality, I'm a little disappointed with the methodology. If I understand correctly, you have to wait for the response object to be returned (with rendered view) before you can do any testing and then you use xpath / css selectors to verify that certain things were in the response. I have no interest in the actual output / response. All I want to know is whether or not the view received the correct variables. What it does with them after that is of no concern to me (at least not while Im testing my controllers). As long as the views get the right information, they can do whatever they want with them...
Am I understanding this correctly? Is my methodology correct?
Although I'm very excited that there is talk of including unit testing functionality, I'm a little disappointed with the methodology. If I understand correctly, you have to wait for the response object to be returned (with rendered view) before you can do any testing and then you use xpath / css selectors to verify that certain things were in the response. I have no interest in the actual output / response. All I want to know is whether or not the view received the correct variables. What it does with them after that is of no concern to me (at least not while Im testing my controllers). As long as the views get the right information, they can do whatever they want with them...
Am I understanding this correctly? Is my methodology correct?
Re: Unit testing Zend Framework Applications
Once again Django does things exactly how I'd like them done... check out how easy and awesome this is: http://www.djangoproject.com/documentation/testing/
There are two unit testing modules built-in to python itself and Django has had built-in unit testing from the ground up. There is a client made specifically for unit testing that returns a django response object with access to what is called a context... which is where the view (or template as they call it) gets its variables.
It's also got support for testing email, authentication, database calls, redirects (and basically any other http stuff) and a bunch of other stuff.
Who wants to help me write something comparable to this for the Zend Framework?

There are two unit testing modules built-in to python itself and Django has had built-in unit testing from the ground up. There is a client made specifically for unit testing that returns a django response object with access to what is called a context... which is where the view (or template as they call it) gets its variables.
Code: Select all
from django.test import TestCase class SimpleTest(unittest.TestCase): def setUp(self): # Every test needs a client. self.client = Client() def test_details(self): # Issue a GET request. response = self.client.get('/customer/details/') # Check that the respose is 200 OK. self.failUnlessEqual(response.status_code, 200) # Check that the rendered context contains 5 customers. self.failUnlessEqual(len(response.context['customers']), 5) Who wants to help me write something comparable to this for the Zend Framework?
Re: Unit testing Zend Framework Applications
Submit a framework proposal, maybe somebody will pick it up
Re: Unit testing Zend Framework Applications
Problem is, to do something like this would require a pretty major overhaul of the mvc architecture. 
Re: Unit testing Zend Framework Applications
Hmm... where's Maugrim_The_Reaper on this one?? 
- Maugrim_The_Reaper
- DevNet Master
- Posts: 2704
- Joined: Tue Nov 02, 2004 5:43 am
- Location: Ireland
Re: Unit testing Zend Framework Applications
Maug is just overwhelmed with stuff
. I can't check the forums daily for the moment, unfortunately...
If you read the proposal, you probably saw my comment on it and Matthew's response. The added support is technically for functional or acceptance testing, not unit testing per se. Common misconception that the proposal will increase no doubt, but unit testing assumes you can test in isolation whereas functional testing (which can use PHPUnit, Selenium, etc.) has no isolation - you test the entire request/dispatch/controller/view process from end to end.
So will this solve your unit testing needs? Probably not to extent needed for TDD (and certainly not BDD). Depends on how you do TDD. In my case, I write Models and Controllers and use extremely basic placeholder views - so it's almost pointless to me. My Views are not concrete during TDD, so functional testing would be disastrous - the moment my View changes to something permanent all my tests would immediately fail. Worse, my Views tend to go through iterations - so fail, fail, and fail again. It's a blackhole of test maintenance. Not to mention what happens when client requirements shift like sand!
You are almost right that it needs an MVC overhaul, so testing is layered far closer to the Controller. The problem is that you can't mock PHP's "new" keyword which is my biggest pain with Controller testing - one solution is to use minimal Dependency Injection (see Zend_Di which has a really light testing API for object/class replacement) so object instantiation in a Controller is abstracted and interceptable. Then tests can literally tell the DI container to instantiate a Mock in place of the original object
. Not incredibly pretty, but PHP doesn't have Ruby's outlook of "new" being a class method to be overridden!
Then apply Mock Objects in place of the Request, objects instantiated in Actions, and Models and you get very close to the ideal. All you then need is a testing framework supporting a spot of automated setup/teardown of requests, and a short API to assertions.
From Matthew's comments on this proposal, and elsewhere, I gather it will be ZF 2.0 before something more invasive is remotely feasible.
If you read the proposal, you probably saw my comment on it and Matthew's response. The added support is technically for functional or acceptance testing, not unit testing per se. Common misconception that the proposal will increase no doubt, but unit testing assumes you can test in isolation whereas functional testing (which can use PHPUnit, Selenium, etc.) has no isolation - you test the entire request/dispatch/controller/view process from end to end.
So will this solve your unit testing needs? Probably not to extent needed for TDD (and certainly not BDD). Depends on how you do TDD. In my case, I write Models and Controllers and use extremely basic placeholder views - so it's almost pointless to me. My Views are not concrete during TDD, so functional testing would be disastrous - the moment my View changes to something permanent all my tests would immediately fail. Worse, my Views tend to go through iterations - so fail, fail, and fail again. It's a blackhole of test maintenance. Not to mention what happens when client requirements shift like sand!
You are almost right that it needs an MVC overhaul, so testing is layered far closer to the Controller. The problem is that you can't mock PHP's "new" keyword which is my biggest pain with Controller testing - one solution is to use minimal Dependency Injection (see Zend_Di which has a really light testing API for object/class replacement) so object instantiation in a Controller is abstracted and interceptable. Then tests can literally tell the DI container to instantiate a Mock in place of the original object
Then apply Mock Objects in place of the Request, objects instantiated in Actions, and Models and you get very close to the ideal. All you then need is a testing framework supporting a spot of automated setup/teardown of requests, and a short API to assertions.
From Matthew's comments on this proposal, and elsewhere, I gather it will be ZF 2.0 before something more invasive is remotely feasible.
Re: Unit testing Zend Framework Applications
YAY! I'm glad you responded paddy! I did see your response and agreed with you completely. I have been doing a lot of research on the subject. I think that if I used a class for my bootstrap instead of a simple file, and if I replaced several of zend's components with my own extensions of them (off the top of my head I'd probably have to extend the front controller, request, response, view, and viewRenderer), I just might be able to test controllers how I've suggested. I'm actually putting together a document about zend's front controller / mvc components to get a better grasp on how things work (as well as teach a co-worker). Once I'm done with it I'm going to study, study, study and hopefully find a way to make the framework unit testable (at the application level) with as little extension as possible. If I could build a fake request, and return an extended response that gives access to the view(s) that its made up of, that just may be enough.
Of course there is going to be a lot more to it because in this case, I'd likely have to mock the database results and in many cases I'd have to mock the sending of an email, the creation / use of cache, and a plethora of other external (hard-to-test) stuff. In the case of the proposal I mentioned, none of these things would be possible.
Also, do you agree that the proposal solves the problem of testing the view / template rather than the controller?
Code: Select all
class TestFooController extends Q_UnitTest_Controller_Action
{
protected $_client;
public function setUp() {
$this->_client = new Q_UnitTest_Controller_Client;
}
public function testBarActionContainsBars() {
$response = $this->_client->request("/foo/bar");
$this->assertEqual($response->getCode(), 200);
$this->assertEqual(count($response->getViewContext()->bars), 10);
}
}Also, do you agree that the proposal solves the problem of testing the view / template rather than the controller?
- Maugrim_The_Reaper
- DevNet Master
- Posts: 2704
- Joined: Tue Nov 02, 2004 5:43 am
- Location: Ireland
Re: Unit testing Zend Framework Applications
You can also take a peek at PHPSpec's subversion repository - before March's loss of focus I was starting to pound up the slope on applying BDD to ZF application development. But yet, the core requirement is a Boostrap Class where the preparation of the application environment is separated from the actual command to the Front Controller to dispatch something. The more separation the better really - even the PHPSpec code was a very early cutout. I can't remember if I even bothered to apply BDD on it since it was more a proof of concept to feel out the requirements.
If you want to know more about PHPSpec's ideal, the API I was aiming for was similar (can't be identical unless you force Dependency Injection) to rspec's.
. It's sufficient for acceptance or functional testing only (if that's what you meant then I readily agree) where you should run the entire application stack (request->controller/model->view->response). But even View testing needs something new. For example, unit tests are development tests - so the key question for a test might be to check a particular controller renders the correct template, the correct set of partials, sets a value in the right Placeholder, etc, rather then test against the output immediately.
I think that borders on pedantry though - it's really only useful if half way through development you still haven't a clue what the basic UI content should be. That is possible, but usually by then you'd have acceptance tests passing which are just about flexible enough you can alter the View quite widely without breaking them all so it should be a rarity.
I think that's probably the whole point - the proposal addresses functional testing only. Nothing else. If you restrict yourself to that view it's quite a good proposal for that one objective.
If you want to know more about PHPSpec's ideal, the API I was aiming for was similar (can't be identical unless you force Dependency Injection) to rspec's.
Actually I'd say it's questionableAlso, do you agree that the proposal solves the problem of testing the view / template rather than the controller?
I think that borders on pedantry though - it's really only useful if half way through development you still haven't a clue what the basic UI content should be. That is possible, but usually by then you'd have acceptance tests passing which are just about flexible enough you can alter the View quite widely without breaking them all so it should be a rarity.
I think that's probably the whole point - the proposal addresses functional testing only. Nothing else. If you restrict yourself to that view it's quite a good proposal for that one objective.
Re: Unit testing Zend Framework Applications
I wouldThe Ninja Space Goat wrote: Who wants to help me write something comparable to this for the Zend Framework?![]()
That's what I'm doing and its working well, bootstrap provides init() and run() methods, the bootstrap gets extended for testing and only init() is called, tests dispatch themselves.The Ninja Space Goat wrote: I think that if I used a class for my bootstrap instead of a simple file
Wouldn't you just subclass the action controller and mock those other components?The Ninja Space Goat wrote: if I replaced several of zend's components with my own extensions of them (off the top of my head I'd probably have to extend the front controller, request, response, view, and viewRenderer)
Link me please to your article(s). I think an abstract factory for model instantiation is in order, no?The Ninja Space Goat wrote: I'm actually putting together a document about zend's front controller / mvc components to get a better grasp on how things work (as well as teach a co-worker). Once I'm done with it I'm going to study, study, study and hopefully find a way to make the framework unit testable (at the application level) with as little extension as possible. If I could build a fake request, and return an extended response that gives access to the view(s) that its made up of, that just may be enough.
Re: Unit testing Zend Framework Applications
Ah, one of many many projects I wanted to start and never got around to. One of these days I'd really love to get back to it, but I doubt it will be any time soon. Are you really interested in doing something like this?
Re: Unit testing Zend Framework Applications
If there was a need for it, I'm not really sure what exactly you would need to be able to test for a controller though