This week has been kicking my ass in terms of work. I’ve started a project at work which is a bit of a rush job (my boss forgot I was at PHP Quebec last week when taking into account the schedule) and I decided that there was no time like the present to start doing things right and start practicing Test Driven Development, or Behaviour Driven Development.
See, this is much harder to do if you inherit some legacy code. Also, as I’ve discovered, Code Igniter is making it difficult to actually write some useful unit tests. The built-in testing tools are terrible (this is not the first time nor the last time I’ve said this) so I am unsure how to approach this. Let me know in the comments of tools you’ve used to help with this in the PHP world.
This new app I’m building using CakePHP, because (a) I’m more familiar with is given the time constraints for the project and (b) it allows me the granular caching that I want. I did consider using Zend Framework for this but time was the enemy. CakePHP is a project that has a culture of testing, and I’ve been using Cake’s CLI test runner. Yes, I know that Zend Framework has the testing culture too, as I remember all the fun I had writing tests for Zend_Service_Audioscrobbler. If you take one thing from this blog post, it’s this: DO NOT USE A FRAMEWORK WITHOUT A CULTURE OF TESTING. You will regret it when you are spending tons of time fixing bugs you should’ve found through unit and functional testing.
In my first week of doing TDD I’ve noticed a subtle change. I’m planning things more. Deciding the output of functions before I actually write them. I’m only creating the functionality I need instead of stubbing out all the functionality I think I’m going to need. I’m looking for ways to run my tests from inside the One True Editor. All of this must be good, right?
PHP does not have a culture of testing at it’s core like Ruby and Python do. I point you at Giles Bowkett and some of the awesome blog posts he’s done about TDD and Ruby. Search that blog and READ THOSE POSTS. You will not regret it.Python has the same culture of testing (doctest is one tool for that), and I don’t know how PHP can get there. Maybe it will never get there because I hazard a guess that most people who use PHP couldn’t give two flying fucks about writing tests. Until that changes (meaning all the cool kids of PHP start writing tests) then TDD will continue to simply result in blank stares in the PHP community.
So I think what TDD is really supposed to do is NOT find bugs. Finding bugs is a side-effect of the process. What it does (at least it did for me) is force you to build you code in such a way that it can be modular and testable. I found myself adding in switches to put functionality into test mode, so that I could load test fixtures instead of hitting a webservice to get my data. You tell me: is that good or bad?
Now I know I haven’t been doing TDD long enough to call myself an expert, but I feel I really need to give it the time and effort that it deserves. This project is the perfect (pardon the pun) testing ground for putting some TDD principles into practice.
Tags: CakePHP, Giles Bowkett, PHP, Python, Ruby, TDD, testing, Zend Framework

By “One True Editor”, I’m assuming you mean vim? Using PHPUnit, you can setup your tests to be self-executable — i.e., you can execute the file through the PHP binary, and it will run the test. It requires adding a conditional before and after the class declaration, and adding a static method for running the test runner, but it’s pretty trivial. I’ve then bound -M (vim’s “make” macro) to execute “php %” for the PHP filetype — which then executes the test. I then split panes, and have one pane editing the test, and the other the class I’m testing.
You have my email, I assume — ping me if you want more details (or I’ll write a blog post).
Putting in switches to change whether you actually hit the webservice? That sounds like test logic in production to me and is something you want to avoid if you can help it. Think in terms of Mock Objects and places that you can pass those in instead of hard coding calls to the web services. It’ll make your life a lot easier down the road
And MWOP’s right, you can run your tests from within Vim pretty easily. Of course, if you were running SimpleTest, it handles it w/o the overhead of extra methods…