Saturday, September 27, 2008

Testing Requirements with Unit Tests

See Testing Requirements with Unit Tests at its new home on bradley-holt.com.

I'm currently working on a project where the client is running their own web server that I will not have direct access to. This is actually a good thing in that it is a nice way to enforce the separation of the development and integration environments from the staging and production environments. However, how do I be sure that all of the system requirements will be met so that I can address any potential problems early on in the project? Sure, I could just give them a file with phpinfo() in it and have them send me the results. However, I plan on also shipping them unit tests for the application so why not have the requirements tested through unit tests as well?

My first thought was, since the application is being built in Zend Framework, just ship them the Zend Framework unit tests. It turns out there are a lot of unit tests and they have some heavy memory requirements. So, I decided on a simpler approach. I would run unit tests that simply tested for the requirements outlined in the Zend Framework documentation. Here are the tests:

/**
* The Requirements test case.
*
* @category Requirements
* @package Requirements
* @copyright Copyright (c) 2005-2008 Found Line, Inc. (http://www.foundline.com/)
* @license http://www.foundline.com/legal/software-license/ New BSD License
*/
class Requirements extends PHPUnit_Framework_TestCase
{

public function testVersionOfPhpIs5Dot1Dot4OrLater()
{
$this->assertTrue(version_compare(PHP_VERSION, '5.1.4', '>='));
}

public function testVersionOfPhpIs5Dot2Dot3OrLater()
{
$this->assertTrue(version_compare(PHP_VERSION, '5.2.3', '>='));
}

/**
* @dataProvider requiredExtensions
* @param string $extensionName the name of the extension for which to test
*/
public function testExtensionLoaded($extensionName)
{
$this->assertTrue(extension_loaded($extensionName));
}

public static function requiredExtensions()
{
return array(
'apc' => array('apc'),
'bcmath' => array('bcmath'),
'bitset' => array('bitset'),
'ctype' => array('ctype'),
'curl' => array('curl'),
'dom' => array('dom'),
'gd' => array('gd'),
'hash' => array('hash'),
'ibm_db2' => array('ibm_db2'),
'iconv' => array('iconv'),
'interbase' => array('interbase'),
'json' => array('json'),
'libxml' => array('libxml'),
'mbstring' => array('mbstring'),
'memcache' => array('memcache'),
'mime_magic' => array('mime_magic'),
'mysqli' => array('mysqli'),
'oci8' => array('oci8'),
'pcre' => array('pcre'),
'pdo' => array('pdo'),
'pdo_mssql' => array('pdo_mssql'),
'pdo_mysql' => array('pdo_mysql'),
'pdo_oci' => array('pdo_oci'),
'pdo_pgsql' => array('pdo_pgsql'),
'pdo_sqlite' => array('pdo_sqlite'),
'posix' => array('posix'),
'reflection' => array('Reflection'),
'session' => array('session'),
'simpleXml' => array('SimpleXML'),
'soap' => array('soap'),
'spl' => array('SPL'),
'sqlite' => array('SQLite'),
'standard' => array('standard'),
'xml' => array('xml'),
'zlib' => array('zlib'),
);
}

}

Note that I've checked for both the recommended PHP version 5.2.3 and the required PHP version 5.1.4. Also, I've tested for both hard and soft dependencies for all components. This means that many of these tests could fail and my application could still be OK. I wanted as much information as possible so that I can detect any potential problems before I write too much code. As the specific requirements for this application become clearer, I will update the test to add or remove requirements. Of course, once there is real code and unit tests these requirements tests will become irrelevant. The point is to test for the presence of these requirements before I write the code.

Running these tests with the command phpunit --testdox Requirements.php (I've actually wrapped this into a bigger test suite, but that's outside the scope of this blog post) gives me the following output on one of my development machines:

PHPUnit 3.3.1 by Sebastian Bergmann.

Requirements
[x] Version of php is 5 dot 1 dot 4 or later
[x] Version of php is 5 dot 2 dot 3 or later
[x] Extension loaded with data set "apc"
[x] Extension loaded with data set "bcmath"
[x] Extension loaded with data set "bitset"
[x] Extension loaded with data set "ctype"
[x] Extension loaded with data set "curl"
[x] Extension loaded with data set "dom"
[x] Extension loaded with data set "gd"
[x] Extension loaded with data set "hash"
[ ] Extension loaded with data set "ibm_db 2"
[x] Extension loaded with data set "iconv"
[x] Extension loaded with data set "interbase"
[x] Extension loaded with data set "json"
[x] Extension loaded with data set "libxml"
[x] Extension loaded with data set "mbstring"
[x] Extension loaded with data set "memcache"
[x] Extension loaded with data set "mime_magic"
[x] Extension loaded with data set "mysqli"
[ ] Extension loaded with data set "oci 8"
[x] Extension loaded with data set "pcre"
[x] Extension loaded with data set "pdo"
[ ] Extension loaded with data set "pdo_mssql"
[x] Extension loaded with data set "pdo_mysql"
[ ] Extension loaded with data set "pdo_oci"
[ ] Extension loaded with data set "pdo_pgsql"
[x] Extension loaded with data set "pdo_sqlite"
[x] Extension loaded with data set "posix"
[x] Extension loaded with data set "reflection"
[x] Extension loaded with data set "session"
[x] Extension loaded with data set "simple xml"
[x] Extension loaded with data set "soap"
[x] Extension loaded with data set "spl"
[x] Extension loaded with data set "sqlite"
[x] Extension loaded with data set "standard"
[x] Extension loaded with data set "xml"
[x] Extension loaded with data set "zlib"


There are a couple of potential problems to be aware of. First, PHPUnit will have to be installed on the machine that this will be tested on. This should probably only be done on the staging machine, not the production machine. Second, the CLI version of PHP often uses a different php.ini file then the CGI or ISAPI version. This means that some requirements may actually be available to your web application but they will fail the test when run at the command line.

Friday, September 26, 2008

ZendCon Highlights Presentation

See ZendCon Highlights Presentation at its new home on bradley-holt.com.

I presented highlights from ZendCon at last night's Burlington, VT PHP Users Group meeting. I've uploaded my slides for anyone who wants to take a look. The presentation uses the S5 slide show format in case you are curious.

Monday, September 22, 2008

ZendCon Highlights at PHP UG Meeting

See ZendCon Highlights at PHP UG Meeting at its new home on bradley-holt.com.

I'll be presenting some highlights from ZendCon at this Thursday's Burlington, VT PHP Users Group meeting. We'll be meeting at Draker Laboratories from 6:00 pm to 8:00 pm. Hope to see you there!

ZendCon 2008

See ZendCon 2008 at its new home on bradley-holt.com.

ZendCon 2008 wrapped up last week. This was my first time going to ZendCon and it was definitely worth it. There were over 650 people and over 60 sessions at the Santa Clara conference. I'll try to post summaries and highlights from the sessions I attended. It was a great opportunity to attended presentations from some of the most well respected people in the PHP community including Vermont's own Matthew Weier O'Phinney (Zend Technologies), Mike Naberezny (Maintainable Software), Sebastian Bergmann (eZ Systems), Derick Rethans (eZ Systems), Ben Galbraith (Ajaxian.com) , Marcus Boerger (Google), and Ben Ramsey (Schematic).

Zend Certified Engineer (ZCE) in Zend FrameworkLast Tuesday during the opening keynote Zend announced the new Zend Framework certification. I was fortunate enough to get a testing slot on Thursday morning. After reading the 214 page study guide on Wednesday I passed the test, so am now a Zend Certified Engineer (ZCE) in Zend Framework! If you plan on taking the test, I definitely recommend reading the study guide. I've been using Zend Framework since 1.0 and I'm not sure I would have passed if I hadn't read the study guide.

Friday, August 29, 2008

Last Night's PHP UG Meeting

See Last Night's PHP UG Meeting at its new home on bradley-holt.com.

Thanks everyone who came out to last night's PHP Users Group meeting - we had the best turnout so far! Lee Brimelow, Platform Evangelist with Adobe, gave a great presentation on Flash, Flex, AMFPHP, and the upcoming Zend_Amf. I thought his presentation was refreshingly straightforward and honest. I have several reservations with using Flash myself and he addressed those issues early on in his presentation. Those issues are primarily search engine issues, accessibility, and "breaking the web model." However, Adobe has not fully answered those questions so I still won't be using Flash except for very specific situations such as video and audio. Regardless, it was an informative presentation and interesting discussion.

Saturday, August 23, 2008

Northeast Pools & Spas Website Launch

See Northeast Pools & Spas Website Launch at its new home on bradley-holt.com.

We just launched the new Northeast Pools & Spas website. I think Dave and Jason did a great job on the visual design and Liz did a fabulous job on organizing and helping to write the content! I worked primarily on the functionality for the construction and portfolio pages. The site is implemented using semantic XHTML, CSS, jQuery, and Zend Framework.

The cool thing about the construction and portfolio pages is that they use progressive enhancement. What this means is that users without JavaScript (i.e. search engine robots & screen readers) can navigate the content by fully reloading the page on each click. You can try this out yourself by disabling JavaScript in your browser. For users with JavaScript, each click on "next" or "previous" (on the construction page) or each portfolio feature (on the portfolio page) will cause their browsers to load the appropriate content dynamically into the right spot on the page without needing a full page reload.

One of the common problems with this type of JavaScript navigation is that you often break the browser's back and forward navigation capabilities. Another common problem is that you can't bookmark the page or send the link to a friend and have the same content loaded. Because these pages update the browser's "hash" we get the browser's back and forward capabilities as well as bookmarkability. The "hash" is the part of the URL that starts with the "#" character. For example, assuming you have JavaScript enabled you should be able to navigate right to the waterfall photo using the following link:

http://www.northeastpools.net/portfolio/#feature/waterfall/

Critiques are welcome!

Friday, August 22, 2008

PHP Users Group Meeting

See PHP Users Group Meeting at its new home on bradley-holt.com.

The next meeting of the Burlington, VT PHP Users Group will be Thursday, August 28th, 2008 at 6pm. Special guest Lee Brimelow, a Platform Evangelist with Adobe and an award-winning interactive designer, will discuss the various ways in which you can integrate PHP with Flash and Flex to create Rich Internet Applications. We will start by covering simple XML exchange and then move on to more high-performance options like AMFPHP. The new proposed support for Adobe's AMF in the Zend Framework will also be discussed. Free software will also be raffled off.