Thursday, November 13, 2008

PEAR and Unit tests - HTTP_Request2

Alexey is chugging away putting together HTTP_Request2, a PHP5 friendly next version of HTTP_Request.

When you look the previous package, HTTP_Request, it's pretty widely used. Within PEAR, these packages make use of it:
* Cache
* File_Sitemap
* HTTP_Client
* HTTP_WebDAV_Client
* Net_CDDB
* Net_DNSBL
* Net_Monitor
* Net_SMS
* pearweb
* Services_Amazon
* Services_Amazon_S3
* Services_Compete
* Services_Delicious
* Services_DynDNS
* Services_ExchangeRates
* Services_Hatena
* Services_OpenSearch
* Services_Pingback
* Services_Technorati
* Services_Trackback (versions <= 0.4.0)
* Services_TwitPic
* Services_W3C_CSSValidator
* Services_W3C_HTMLValidator
* Services_Weather
* Services_Yadis
* Services_Yahoo
* SOAP
* Testing_Selenium (versions <= 0.2.1)
* XML_GRDDL

Outside of PEAR; I'm sure there are lots more direct uses of HTTP_Request.

I know it's a valuable part of my code kung-fu kit and I love its API simplicity. It just works. Works well, too.


So HTTP_Request2 is the next iteration of the package - it features the notion of Adapters, so you can use the HTTP library of your choice - be it CURL, be it raw sockets, or for the more esoteric, TCP/Pidgeon.

The other great bit to this is the Mock Adapter. That's right ladies and gents; unit testing just got a whole lot better - just inject an instance of HTTP_Request2 with the Mock Adapter in, and have your tests run in mere moments!

A Quick Example


Observe how you might choose to execute all possible paths in this googlez() function.

<?php
require_once 'HTTP/Request2.php';
require_once 'HTTP/Request2/Adapter/Mock.php';

function googlez(HTTP_Request2 $client) {
$response = $client->send();

switch ($response->getStatus()) {
case '400':
print "YAY; we gots a response, we can haz googlez\n";
return true;
break;
case '403':
print "NAOOOOOO googlez forbidden\n";
return false;
break;
}
}


$mock = new HTTP_Request2_Adapter_Mock();
$mock->addResponse(new HTTP_Request2_Response('HTTP/1.1 400 Success'));
$mock->addResponse(new HTTP_Request2_Response('HTTP/1.1 403 Forbidden'));

$client = new HTTP_Request2('http://google.com/');
$client->setAdapter($mock);


// I can has googlez?
assert(googlez($client) === true);

// LOLWUT; I shouldz find out wha happenz if google explodez
// I fink it willz give me false.
assert(googlez($client) === false);


If you are doing it right, you will get:

YAY; we gots a response, we can haz googlez
NAOOOOOO googlez forbidden

Swapping this over to PHPUnit would be trivial.

Keep your ears open for the upcoming HTTP_Request2 release, and I would strongly encourage people to adopt it for their existing packages :)

No comments: