views:

199

answers:

5

I'm writing Yet Another PHP Framework, and now that I've coded a good deal of stuff, I'm starting to think about unit tests (yes, I know, bad form).

Some actions make the framework to modify HTTP behavior, such as create cookies, redirect the browser. Another major feature is that the the visited URI can affect the way the framework should behave.

In a nutshell, I need to be able to test stuff that affect, or are affected by, the environment, and not only the return values of functions/methods. How can I do this the easiest?

+4  A: 

SimpleTest's Web Tester may be of help to you.

Click Upvote
I find the Simpletest web/form tester is easier than the PHPunit tools for this. I've actually had both main authors, side by side and asked them if they could integrate ST's WT into PHPUnit. Here's hoping.
Alister Bulman
Or when you need to also test JavaScript on your pages and do some cross-browser testing, then you might want to take a look at Selenium.
Rene Saarsoo
That's weird - I'm pretty sure I stumbled upon SimpleTest before, but never got the impression it's this involved. This very much might be what I'm after. Thanks for the link, this requires more detailed investigation. Stand by for "accepted answer".
Henrik Paul
A: 

So it sounds as though you are writing integration tests and not unit tests (by definition anything which touches the environment is an integration test).

Would this be easier to test through the stack through the browser? If so have a look at a browser automation framework, maybe something like http://wtr.rubyforge.org/

Codebrain
+2  A: 

In a nutshell, I need to be able to test stuff that affect, or are affected by, the environment, and not only the return values of functions/methods. How can I do this the easiest?

If the environment can be simulated easily and can be represented completely with a small amount of state, then you should look into mock testing. Mock tests help you write tests without the mess of having to use real domain objects, if you can get away with simply making sure that things were called in the right order. Here's a good overview of the principles.

If that's not the case, then you're talking about an integration test, which is significantly more expensive. Integration tests help you see if your system is cohesively formed and usually run with a live, full-stack copy of your application. Here's some more reading on integration tests.

John Feminella
The environment is not easy to completely represent. Besides, if I manually generate stimuli, I'd rather not take the chance of generating the wrong things (i.e. not formatting stuff correctly.)
Henrik Paul
But, yes, if you want to call it integration tests (I'm not 100% on the clear on the nuances between test and test. I just want to make sure everything's running as intended), It's all good. What I'm interested in, though, is the 'how', not as much the 'what'.
Henrik Paul
+1  A: 

You should make HTTP requests to the server in your unit tests, and then check that cookies and headers are set correctly in the response.

In PHP, I would use Zend_Http_Client. Documentation can be found here, in the package Zend_Http.

gnud
A: 

(yes, I know, bad form).

Yes. If you had started with the tests, you would have written your framework in a way, such that external dependencies could be mocked out. What you can do now, is to replace all calls to functions that manipulate global state, with a call to a global proxy object. You can then mock this out during tests. One particular troublesome change of global state, is calls to exit/die. You could try to replace this with an exception in your mock.

troelskn
I thought of this (Zend Framework seems to do that). But isn't there a point of possible failure between the proxy object and its signals to the actual environment? I still would need to test that, wouldn't I?
Henrik Paul
You generally can't test those kind of adapters through unit tests; You'll have to rely on integration-tests (webtest) for that. But you'd want to test those things separately from each other, rather than just running everything through webtests. A unit test is much more exact, and allows mocking.
troelskn