Unit testing is something that every project really should do - so you can see where things go wrong. So as I consolidate some of my junk into callicore I'm trying to make it easier to keep track of. I'd almost like to use trac - but there's something in my soul that rebels against using a python project to manage a php project - I'm just weird like that.
Now that there's an svn extension for php someone should really do a trac style clone...
Anyway - there are several php implementations of unit testing frameworks. phpUnit and SimpleTest are the top of the heap. But quite frankly - they're HUGE. Unneccesarily huge and bulky and "aiming to be a full port of Junit" - WHY??? This is php, not java...
Anyway, I was less than impressed with the sheer annoyance factor of using either one. Then there's php's test system (phpt) - and their cool gcov site . Although automated testing and code coverage is something I would like, I'm not testing C and OO doesn't always conform too well to php's test system.
So once again, I'm forced to roll my own.
What do I want from a test system?? Well I'd like flexible reporting, code coverage which can only be done via xdebug (where are my 5.2 snaps, pecl4win???), line counting for code...heck theoretically even comment checking
Most unittest suites start with the basics of doing asserts - assertTrue, assertFalse, assertdoyourownhere... Php even has a basic assert(this must be true) - but php's assert has a really big weakness, it doesn't work well in an OO setting and you can't just throw in additional items (like maybe a message on failure?) so the sad but funny thing is that instead of using php's assert most of these systems have to rewrite it.
Php's assert function works like this - you pass in a string and it gets eval'ed, if assert is active and either a callback is set or throwing a php warning is set - and the eval'ed is false - then we trigger the callback - voila! But it's annoying to have to send a string in order to get the assert code.
Exceptions make life easier when writing a test system because you can use them to "jump" out of code - they're not really SUPPOSED to be used for that purpose, but hey it's useful. Callicore uses an error handler when running tests that transforms any error to an exception - so you can tell if your test failed or if you had an error - two entirely different conditions. The testunit class is abstract and is supposed to be extended by every test.
Right now I only have an assert method - it checks to see if what you send is true. I find the "fine grained" assertions (assertTrue, assertFalse, blah blah) overkill. But to gather the actual code passed to the assertion - that can be a pain. Right now I run a debug_backtrace to grab the line the assertion was on, read in the file and grab that line, preg_match the actual assert, and then unset the trace and the file to clean up memory. I'm sure there has to be a better way but I haven't found it yet. Probably buried somewhere in Reflection but I haven't found it yet.
I'm also undecided about doing a new instance of a class for every test - something PhpUnit does via reflection, and simpletest uses a whole invoker class for...nuts.
Anyway - the initial three classes I'm using for unit testing are in subversion now along with a fairly long todo list for the test stuff. I have a test report class I'm currently hacking on. We'll see how much I can short that todo in the next few days.