<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Bill Shupp &#187; Code</title>
	<atom:link href="http://blog.shupp.org/category/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.shupp.org</link>
	<description>Software engineer, musician, space enthusiast</description>
	<lastBuildDate>Fri, 03 Feb 2012 22:00:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>Getting started with Kestrel from a PHP application</title>
		<link>http://blog.shupp.org/2011/05/07/getting-started-with-kestrel-from-a-php-application/</link>
		<comments>http://blog.shupp.org/2011/05/07/getting-started-with-kestrel-from-a-php-application/#comments</comments>
		<pubDate>Sun, 08 May 2011 00:15:49 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Kestrel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=8235</guid>
		<description><![CDATA[We've been using Twitter's kestrel queue server for a while now at work, but only from our service layer, which is written in python.  Now that we have some queueing needs from our application layer, written in PHP, I spent a few days this week adding queue support to our web application.  I thought I'd [...]]]></description>
			<content:encoded><![CDATA[<p>We've been using Twitter's <a title="Kestrel" href="https://github.com/robey/kestrel">kestrel queue server</a> for a while now at work, but only from our service layer, which is written in python.  Now that we have some queueing needs from our application layer, written in PHP, I spent a few days this week adding queue support to our web application.  I thought I'd share what I learned, and how I implemented it.</p>
<p><strong>Goals</strong></p>
<p>The kestrel server itself was pretty straightforward to get up and running.  The only thing I would point out is that I recommend sticking to release branches, as master was fairly unstable when I tried to use it.  Regarding implementing the client, there were a few goals I had in mind when I started:</p>
<ul>
<li>Since kestrel is built on the memcache protocol, try and leverage an existing memcache client rather than build one from scratch</li>
<li>Utilize our existing batch job infrastructure, which I covered previously <a title="Organizing PHP Batch Jobs" href="http://blog.shupp.org/2011/03/15/organizing-php-batch-jobs/">here</a>, and make sure our multi-tenant needs are met</li>
<li>Keep the queue interface generic in case we change queue servers later</li>
<li>Utilize existing kestrel management tools, only build out the the functionality we need</li>
</ul>
<p>With these goals in mind, I ended up with 4 components: a kestrel client, a producer, a consumer, and a very small CLI harness for running the consumer.  But before I even coded anything, I set up <a title="Kestrel Web" href="https://github.com/matterkkila/kestrelweb">kestrel web</a>, a web UI for kestrel written by my co-worker Matt Erkkila.  Kestrel web allows you to view statistics on kestrel, manage queues, as well as sort and filter queues based on manual inputs.  Having this tool up and running from the get go made it easy to watch jobs get added and consumed from my test queue, and also easily flush out the queues as needed.<span id="more-8235"></span></p>
<p><strong>The Kestrel Client</strong></p>
<p>I couldn't find any existing kestrel clients for PHP, so I started looking at the two memcache extensions: the older memcache, and Andrei Zmievski's memcached, the latter of which is based on the libmemcached library.  I started with memcache, and while it worked fine initially, I quickly found that I could not modify timeouts.  This interfered with the way  kestrel recommends you poll it for new jobs, and I would see timeout errors from the memcache extension if you tried to set the poll timeout to 1 second or higher (the memcache default).  The memcached extension does not have these issues, so I went with it.</p>
<p>The first gotcha I ran into was serialization.  You can use memcached's serializer for writing to kestrel, but when it reads the data back, it doesn't recognize that it is serialized.  So I just serialize the data manually in my client, and things work fine.  One other thing to note is that you'll want to disable compression, or do it manually, as the memcached extension will automatically compress anything over 100 bytes by default, and will not decompress it when reading from kestrel.</p>
<p>The other issue is that if you want to use any custom kestrel commands, you can't.  Since the application layer doesn't need anything fancy, the memcached extension will work fine for it.  Once we need support for the upcoming monitor (batching) in kestrel 2, we may need to implement a kestrel client from scratch.  Kestrel web supplies everything else we need right now.</p>
<p>Once the decision was made to use memcached, I wrote a light decorator for it, EC_KestrelClient.  This handles instantiation of the memcached client, serialization, and helpers for some kestrel specific options to the GET command.  It also has support for passing memcached specific options through it.  The class ended up looking like this:</p>
<p><script src="https://gist.github.com/960968.js?file=EC_KestrelClient.php"></script></p>
<p><strong>The Producer</strong></p>
<p>The producer is very simple.  It just formats the data into a standard structure, including current tenant information, namespaces the queue so it doesn't collide with other projects, and adds it to the queue.  The producer looks like this:</p>
<p><script src="https://gist.github.com/960963.js?file=EC_Producer.php"></script></p>
<p><strong>The Consumer</strong></p>
<p>The consumer has a bit more to it, though still pretty straightforward.  It's intended to be run from a monitoring tool like <a title="Daemontools" href="http://cr.yp.to/daemontools.html">daemontools</a> or <a title="Supervisord" href="http://supervisord.org/">supervisord</a>, so there is a very small CLI harness that just passes the CLI arguments into EC_Consumer and runs it.  After parsing the CLI arguments, EC_Consumer polls kestrel for new jobs, and runs them through our standard batch job infrastructure.  Until we have more confidence in PHP's long running process ability, I added an optional maxium jobs argument, which will stop the consumer from processing more than X jobs and then terminate.  The monitoring service (supervisord) will then just restart it in a matter of seconds.  I also added an optional debug argument for testing, so you can see every action as it happens.  The CLI harness looks like this:</p>
<p><script src="https://gist.github.com/960957.js?file=consumer_cli.php"></script></p>
<p>And the main consumer class, EC_Consumer, looks something like this:</p>
<p><script src="https://gist.github.com/960974.js?file=EC_Consumer.php"></script></p>
<p><strong>Putting it together</strong></p>
<p>Now that all the pieces are put together, let's take a look at in action.  Adding example job "HelloWorld" to the queue "hello_world" from within our application looks something like this:</p>
<p><script src="https://gist.github.com/960980.js?file=gistfile1.php"></script></p>
<p>And finally, here's an example of running the consumer from the CLI harness, along with some example debug output of processing the job:</p>
<p><script src="https://gist.github.com/960979.js?file=example.txt"></script></p>
<p>That's it!  I'd be interested to hear how other folks are interfacing with kestrel from PHP.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/05/07/getting-started-with-kestrel-from-a-php-application/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>More on step debugging in PHP</title>
		<link>http://blog.shupp.org/2011/04/18/more-on-step-debugging-in-php/</link>
		<comments>http://blog.shupp.org/2011/04/18/more-on-step-debugging-in-php/#comments</comments>
		<pubDate>Tue, 19 Apr 2011 06:43:27 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHPUnit]]></category>
		<category><![CDATA[Unit Testing]]></category>
		<category><![CDATA[VIM]]></category>
		<category><![CDATA[Xdebug]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=8170</guid>
		<description><![CDATA[Having recently wrote about PHP step debugging in VIM, I thought I'd share a couple of things I've come across since writing it. First, I find that I often need step debugging when writing unit tests, as that's when I'm really scrutinizing logic.  It turns out it's pretty easy to do.  All you need is [...]]]></description>
			<content:encoded><![CDATA[<p>Having recently wrote about <a href="http://blog.shupp.org/2011/02/12/php-step-debugging-in-vim/">PHP step debugging in VIM</a>, I thought I'd share a couple of things I've come across since writing it.</p>
<p>First, I find that I often need step debugging when writing unit tests, as that's when I'm really scrutinizing logic.  It turns out it's pretty easy to do.  All you need is to set the XDEBUG_CONFIG environment variable like so:</p>
<p><code>XDEBUG_CONFIG="idekey=session_name" php bin/phpunit.php tests/FooTest.php</code></p>
<p>When debugging from VIM, you'll want to have two shells open.  One running the debugger, and another executing the tests.  Also, note that in a shared environment, you can still pass in xdebug ini settings like so:</p>
<p><code>XDEBUG_CONFIG="idekey=session_name" \<br />
    php -d xdebug.remote_host=10.0.0.1 bin/phpunit.php tests/FooTest.php</code></p>
<p>Second, for step debugging in VIM, I've settled on <a title="VIM Plugin" href="http://www.vim.org/scripts/script.php?script_id=2508">this plugin</a> (there are many versions out there).  It seems to solve problems with tab handling that I was seeing with older versions.</p>
<p>Cheers,</p>
<p>Bill</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/04/18/more-on-step-debugging-in-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Preparing your application for serving static content efficiently</title>
		<link>http://blog.shupp.org/2011/03/21/preparing-your-application-for-serving-static-content-efficiently/</link>
		<comments>http://blog.shupp.org/2011/03/21/preparing-your-application-for-serving-static-content-efficiently/#comments</comments>
		<pubDate>Tue, 22 Mar 2011 03:49:17 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=7898</guid>
		<description><![CDATA[(Reposted from the Empower Campaigns blog) Most web applications have static content such as CSS, JS, images, etc.  To save on bandwidth costs and improve load times for your users, it's a good idea to tell the client to cache these items for a long period of time.  But even though your static content changes [...]]]></description>
			<content:encoded><![CDATA[<p><em>(Reposted from the Empower Campaigns <a title="Orignal Post" href="http://blog.empowercampaigns.com/post/4007131732/preparing-your-application-for-serving-static-content">blog</a>)</em></p>
<p>Most web applications have static content such as CSS, JS, images,  etc.  To save on bandwidth costs and improve load times for your users,  it's a good idea to tell the client to cache these items for a long  period of time.  But even though your static content changes  infrequently, when it does, the cached content needs to be invalidated.   In addition, high traffic sites often want to go a step further and  take advantage of a <a title="Content Delivery Network" href="http://en.wikipedia.org/wiki/Content_delivery_network">CDN</a> to offload static content delivery.  Below I'll share the method we used here at <a title="Empower Campaigns" href="http://empowercampaigns.com">Empower Campaigns</a> to accomplish both of these things.<img src="http://assets.tumblr.com/javascript/tiny_mce_3_3_3/plugins/pagebreak/img/trans.gif" alt="" /><span id="more-7898"></span></p>
<p><strong>Version your content</strong></p>
<p><strong> </strong>The first step to getting control of cache  invalidation is to manage the version of your content, usually included  as part of the URL.  In the past I've seen things like incrementing a  single counter for your JS and CSS files that effectively changed the  URL of these files and invalidated the cache.  But this updates the URL  for ALL of the files that use that counter, which is not very  efficient.  A better approach is to version each file (or bundle, if you  deliver files in groups) so that you control the cache invalidation of  each item individually.  One way to do this is with a hash like <a title="Cyclic redundancy check" href="http://en.wikipedia.org/wiki/Cyclic_redundancy_check">CRC32</a>.   If the content is stored on a file system, such as JS, CSS, or image  files often are, you could hash the file upon the first read, and store  that hash in a cache that gets purged during a production code push.   For PHP users, <a title="APC" href="http://us.php.net/manual/en/book.apc.php">APC</a> is a great tool for this.  This reduces the hashing overhead to one  time per web node in your cluster per code release.  If your content is  stored somewhere outside of your code base, you might consider storing  the hash of the content at write time.  For example, when I worked at <a title="Digg" href="http://digg.com">Digg</a>, we stored user profile images in <a title="MogileFS" href="http://danga.com/mogilefs/">MogileFS</a>.   So when a user added or changed their profile image, we would hash the  image at that time and store the hash with that user's profile data in <a title="Cassandra" href="http://cassandra.apache.org/">Cassandra</a>.   This was even better because the content was hashed only once.  The  same type of thing could be done with locally stored content, it just  depends how fancy you'd like to get.  Note that when constructing your  versioned URL, avoid using the version in the query string, as some CDNs  strip query strings (ex:  media.yourdomain.com/v/8bba8b90/css/960.min.css rather than  media.yourdomain.com/css/960.min.css?v=8bba8b90)</p>
<p><strong>Minify/Compress your content</strong></p>
<p>In a production environment, you want to deliver static content as  quickly as possible.  Two ways to help with this is minification and  compression.  For minification, we use Google's <a title="Google Closure" href="http://code.google.com/closure/">Closure</a> for JS, and <a title="YUI Compressor" href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a> for CSS, both of which are run during the deployment process.  You'll  also want to enable compression in your web server as well, such as  mod_deflate in Apache, to make the files as small as possible during  transit.<strong> </strong></p>
<p><strong>Increase cache time</strong></p>
<p>Once you have your content versioning in place, you'll want to  increase the cache time for those files.  We use a cache time of one  year, and set that at the web server level like so using mod_rewrite:</p>
<p><script src="https://gist.github.com/879761.js?file=gistfile1.txt"></script></p>
<p><strong>Use a dedicated domain name</strong></p>
<p>If you want to be ready to move to a CDN at any time, consider  putting your static content on a dedicated virtual host, such as  media.yourdomain.com.  This way, you can simply point that domain to a  CDN at any time, and you'll be up and running.  Also, this has the added  benefit of allowing the client's browser to make more parallel requests  for your content, as they often limit the number of parallel requests  they'll make to any one domain.  By spreading your content over more  than one domain, the client can make more requests in parallel, speeding  up the the time for the document to be ready.  One other benefit is  that by using another domain for your media, you can reduce the number  of cookies sent with media requests, which reduces the size of each  request.  Our rewrite rules for ignoring version numbers in our media host ended up looking like this:  <script src="https://gist.github.com/879762.js?file=gistfile1.txt"></script></p>
<p>With  the above steps in mind, we wrote a view helper that handles hashing  and url writing called mediaURL().  It can also look at our config and  determine if SSL URLs should be used, if a given page in our application  requires it.  The view helper looks like this:</p>
<p><script src="https://gist.github.com/879949.js?file=gistfile1.php"></script> And the call to the helper from our view looks like this:  <script src="https://gist.github.com/879805.js?file=gistfile1.html"></script></p>
<p><strong>Conclusion</strong></p>
<p>By following the steps above, you'll have static content that is  dynamically versioned, compressed, and cacheable by the client.  And if  you're serving it on a dedicated domain, you'll speed up overall page  load times and be ready to provision a CDN if you ever need it.</p>
<p>Cheers,</p>
<p>Bill Shupp, Lead Developer (twitter: <a title="My Twitter Account" href="http://twitter.com/shupp">http://twitter.com/shupp</a>)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/03/21/preparing-your-application-for-serving-static-content-efficiently/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Organizing PHP Batch Jobs</title>
		<link>http://blog.shupp.org/2011/03/15/organizing-php-batch-jobs/</link>
		<comments>http://blog.shupp.org/2011/03/15/organizing-php-batch-jobs/#comments</comments>
		<pubDate>Wed, 16 Mar 2011 06:50:00 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=7802</guid>
		<description><![CDATA[This week at work I got the chance to address the growing number of batch oriented CLI scripts for our main web application.  While they weren't quite unmanageable yet, they were heading in that direction.  There was too much common code, especially with bootstrapping the application and parsing options.  Also,  the location of scripts didn't [...]]]></description>
			<content:encoded><![CDATA[<p>This week at work I got the chance to address the growing number of batch oriented CLI scripts for our main web application.  While they weren't quite unmanageable yet, they were heading in that direction.  There was too much common code, especially with bootstrapping the application and parsing options.  Also,  the location of scripts didn't really make sense... <code>./bin/bar.php</code>,  <code>./cron/foo.php</code>, etc.  So I decided to carve out some time and clean it up.</p>
<p>The goals were pretty straight forward:</p>
<ul>
<li>Everything must use the application's <a title="Deneb" href="http://github.com/empower/Deneb">model layer</a>.  This is mostly so that the built in caching will be consistent, but also to enforce that all data access goes through the same code.</li>
<li>Centralize all CLI option parsing, application bootsrapping, error handling, and multi-tenant logic (this is a multi-tenant SaaS application)</li>
<li>Keep the jobs themselves very simple.</li>
</ul>
<p>With the above in mind, I ended up splitting things up into 3 parts:<span id="more-7802"></span></p>
<ul>
<li><code>./bin/ecli.php</code>, the only PHP CLI script which does minimal bootstrapping, collects the options/arguments, and runs <code>EC_CLI</code></li>
<li><code>EC_CLI</code>, a class that does the actual option parsing (via <code>Zend_Console_Getopt</code>), application bootstrapping, error handling, and multi-tenant runs (recursively calls <code>./bin/ecli.php</code> for each tenant), and runs the actual job</li>
<li><code>EC_Job_Abstract</code>, the Job interface that collects job specific arguments and runs the job.</li>
</ul>
<p>Now, when I need to create a new batch job <code>EC_Job_Foo</code>, I just put the contents in <code>EC_Job_Foo::run()</code>, and execute it like so:</p>
<p><code>./bin/ecli.php --environment production --instance clienta,clientb --job Foo</code></p>
<p>The <code>ecli.php</code> script ends up looking like this:<br />
<script src="https://gist.github.com/872101.js?file=ecli.php"></script></p>
<p>Pretty easy, huh?  It makes testing all the components really easy as well.</p>
<p>Finally, we made the decision to use <a title="Jenkins CI" href="http://jenkins-ci.org/">Jenkins</a> instead of the traditional cron scheduler for recurring jobs.  This has a few advantages: It's got a simple web interface for managing the job, you plug it into your existing Jenkins notifications (email, jabber, etc), console tailing, job dependencies, etc... It works really well.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/03/15/organizing-php-batch-jobs/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>PHP step debugging in VIM</title>
		<link>http://blog.shupp.org/2011/02/12/php-step-debugging-in-vim/</link>
		<comments>http://blog.shupp.org/2011/02/12/php-step-debugging-in-vim/#comments</comments>
		<pubDate>Sun, 13 Feb 2011 00:17:55 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[VIM]]></category>
		<category><![CDATA[Xdebug]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=7182</guid>
		<description><![CDATA[When debugging problems in PHP, most of the time it's easiest to just add var_dump($foo); exit; in the middle of your script, and you can see the contents of $foo right in your browser.  But if you have to do much more, this approach gets cumbersome pretty quickly.  I've recently been using step debugging for [...]]]></description>
			<content:encoded><![CDATA[<p>When debugging problems in PHP, most of the time it's easiest to just add <code>var_dump($foo); exit;</code> in the middle of your script, and you can see the contents of <code>$foo</code> right in your browser.  But if you have to do much more, this approach gets cumbersome pretty quickly.  I've recently been using <a title="Program Animation" href="http://en.wikipedia.org/wiki/Program_animation">step debugging</a> for harder to track down problems.  It allows me to examine the state of things all the way through execution of a request, line by line, or skipping ahead to break points.  This process also gives you more insight into everything else happening in a request, which can be useful when you're using frameworks or other 3rd party code in your application.<span id="more-7182"></span></p>
<p>With PHP, the common extension for this is <a title="Xdebug" href="http://xdebug.org">Xdebug</a>.  (See the remote debugging documentation <a title="Xdebug remote documentation" href="http://www.xdebug.org/docs/remote">here</a>).  Since my main text editor is <a title="VIM" href="http://vim.org">VIM</a>, I had to find a suitable plugin to talk to Xdebug.  It turns out there are a few good blog posts already on this topic, so I won't duplicate the information here.  <a title="VIM/Xdebug tutotrial" href="http://2bits.com/articles/using-vim-and-xdebug-dbgp-for-debugging-drupal-or-any-php-application.html">This post</a> does a great job of covering installation and usage of the Xdebug plugin for VIM by Seng Woo Shin, though it links to an older version of it.  Here's a <a title="xdebug plugin" href="http://www.vim.org/scripts/script.php?script_id=1929">link</a> to a newer one that Xdebug also links to.  The Xdebug site links to <a title="Xdebug/VIM tutorial" href="http://tech.blog.box.net/2007/06/20/how-to-debug-php-with-vim-and-xdebug-on-linux/">another tutorial</a> that's worth a read too.</p>
<p>Beyond the links above, I've discovered a couple of things that are worth sharing.  First, there's a new FireFox extension, <a title="Firefix Extension" href="https://addons.mozilla.org/en-US/firefox/addon/58688">easy Xdebug</a>, that is a real lifesaver.  You just click the green bug on the bottom right, and it will try to start an Xdebug session with any request (rather than having to add XDEBUG_SESSION_START=1 to the query string parameters myself).  This is particularly handy when dealing with POST or or AJAX requests.  The Xdebug <a title="Xdebug remote documentation" href="http://www.xdebug.org/docs/remote">docs</a> also link to similar tools for Chrome, Safari, and Opera.</p>
<p>Now, my debugging work flow looks like this:</p>
<ul>
<li>Start the Xdebug session in FF by clicking the green bug</li>
<li>Set breakpoints in VIM</li>
<li>Press F5 in VIM to start listening for the request (it waits 5 seconds)</li>
<li>Perform that action I want to debug in FF</li>
<li>Press enter in VIM to enter the debug session</li>
<li>Debug</li>
<li>Press F6 to exit debugger, and fix the problem</li>
</ul>
<p>The one gotcha that I keep running into is how to set breakpoints correctly.  <strong>When you use this VIM plugin, you must put a breakpoint on executable code</strong>.  If you put it on a blank line, or even on a line with just an opening <code>try</code> statement, your breakpoint will not work.  Instead, you'll end up with an "error 5".  This topic is briefly covered <a title="breakpoint issue" href="http://ubuntuforums.org/showthread.php?t=1074820">here</a> and <a title="breakpoint issue" href="http://xdebug.org/archives/xdebug-general/1202.html">here</a>.</p>
<p>Now, when I find myself using more than one or two <code>var_dump()</code> statements to debug something, I usually walk through the work flow above, and have things sorted out much more quickly than I used to.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2011/02/12/php-step-debugging-in-vim/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>GitHub Pages + Pirum = Easy PEAR Channel</title>
		<link>http://blog.shupp.org/2010/12/24/github-pages-pirum-easy-pear-channel/</link>
		<comments>http://blog.shupp.org/2010/12/24/github-pages-pirum-easy-pear-channel/#comments</comments>
		<pubDate>Sat, 25 Dec 2010 06:00:07 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[GitHub]]></category>
		<category><![CDATA[PEAR]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=6895</guid>
		<description><![CDATA[I prefer managing my non-PEAR PHP dependencies (such as Zend Framework and PHPUnit) through PEAR channels when possible.  It's much easier to manage component installation, upgrades, etc..  Managing and hosting a PEAR channel (using the Chiara_PEAR_Server) is not always that simple, and can add too much overhead for small projects.  I like how Zend Framework [...]]]></description>
			<content:encoded><![CDATA[<p>I prefer managing my non-<a title="PEAR" href="http://pear.php.net">PEAR</a> PHP dependencies (such as <a title="Zend Framework" href="http://framework.zend.com">Zend Framework</a> and <a title="PHPUnit" href="http://phpunit.de">PHPUnit</a>) through PEAR channels when possible.  It's much easier to manage component installation, upgrades, etc..  Managing and hosting a PEAR channel (using the <a title="Chiara PEAR Server" href="http://pear.chiaraquartet.net/index.php?package=Chiara_PEAR_Server">Chiara_PEAR_Server</a>) is not always that simple, and can add too much overhead for small projects.  I like how Zend Framework leveraged google code to host its PEAR channel, and was able to update it simply through pushing to SVN, avoiding a web interface.  Since I've been accumulating some components recently that really don't fit into pear.php.net, I figured it was time set up a PEAR channel for distributing them, but didn't want to host it myself or have to use a web interface.   Turns out, it's really easy to do now.<span id="more-6895"></span></p>
<p><strong>Hosting using GitHub Pages</strong></p>
<p>Since I prefer <a href="http://github.com">GitHub</a> to <a href="http://code.google.com">Google Code</a> for hosting my open source repositories, I decided to take a look at their new <a title="GitHub Pages" href="http://pages.github.com">Pages</a> feature for project web hosting.  It's <em>super</em> easy to set up.  You can host content at <em>http://username.github.com</em> by creating a repository <em>username.github.com</em> (master branch), and can also host project related content at <em>http://username.github.com/project</em> by creating a top level <em>gh-pages</em> branch in the project.  I was up and running in minutes.  See <a title="GitHub Pages" href="http://pages.github.com">here</a> for specific instructions on setting it up.</p>
<p><strong>PEAR Channel Serving with Pirum</strong></p>
<p>I wasn't sure what the ZF guys were using to manage their channel, so I started by looking at <a title="PEAR2" href="http://pear2.php.net">PEAR2</a>'s <a title="SimpleChannelServer" href="http://pear2.php.net/PEAR2_SimpleChannelServer">SimpleChannelServer</a>.  While it looks promising, and you can even manage it directly from pyrus, I ran into enough errors that I thought I'd take a look <a title="Pirum" href="http://pirum-project.org">Pirum</a>, another simple channel server written by the <a title="Symfony" href="http://symfony-project.org">Symfony</a> project maintainer.  It worked for me right out of the box.  Setup was as simple as:</p>
<p><code><br />
pear channel-discover pear.pirum-project.org<br />
pear install pirum/Pirum<br />
cd ~/git/pirum<br />
# create pirum.xml file<br />
pirum build .<br />
# commit changes and push to github<br />
</code></p>
<p>So now releases through my PEAR channel look like this:</p>
<p><code><br />
# update PEAR package.xml, then run:<br />
pear package<br />
cd ~/git/pirum<br />
pirum add . ~/git/deneb/Deneb-0.3.0.tgz<br />
# commit changes and push to github<br />
</code></p>
<p>Now I've got an easily managed PEAR Channel that I don't have to host:  <a title="Bill Shupp's PEAR Channel" href="http://shupp.github.com/pirum">http://shupp.github.com/pirum</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2010/12/24/github-pages-pirum-easy-pear-channel/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Better code quality through easy access to tools</title>
		<link>http://blog.shupp.org/2010/09/20/better-code-quality-through-easy-access-to-tools/</link>
		<comments>http://blog.shupp.org/2010/09/20/better-code-quality-through-easy-access-to-tools/#comments</comments>
		<pubDate>Tue, 21 Sep 2010 03:39:43 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHPUnit]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=7891</guid>
		<description><![CDATA[(Reposted from the Empower Campaigns blog) When developing an application, one of the keys to maintaining high productivity and quality is to make sure that you not only have the right tool set, but that you have easy access to it.   With web applications, the usual needs are things like running Selenium tests, running unit [...]]]></description>
			<content:encoded><![CDATA[<p><em>(Reposted from the Empower Campaigns <a title="Original Empower Campaigns Blog" href="http://blog.empowercampaigns.com/post/1156820644/better-code-quality-through-easy-access-to-tools">blog</a>)</em></p>
<p>When developing an application, one of the keys to maintaining high  productivity and quality is to make sure that you not only have the  right tool set, but that you have easy access to it.   With web  applications, the usual needs are things like running <a title="Selenium" href="http://seleniumhq.org/">Selenium</a> tests, running unit tests and checking code coverage, profiling, and having links to documentation.  Though I've <a title="stated previously" href="http://blog.shupp.org/2010/02/21/pragmatic-tips-for-unit-testing-in-php/">talked previously</a> about the cost of maintaining 100% code coverage, I'm convinced that  it's worth it if you not only get proficient at the tools, but make them  very easy to use.  So when I started as the first developer here at <a title="Empower Campaigns" href="http://empowercampaigns.com">Empower Campaigns</a> a couple of months ago, I wanted to make sure these needs were addressed early on, before we had a large development team.<span id="more-7891"></span></p>
<p><img src="http://assets.tumblr.com/javascript/tiny_mce_3_3_3/plugins/pagebreak/img/trans.gif" alt="" />Inspired by the work that had been done at my previous job by <a title="Ian Eure" href="http://atomized.org">Ian Eure</a> and <a title="Matt Erkkila" href="http://matterkkila.com">Matt Erkkila</a>, I decided to start with the following:</p>
<ul>
<li>Use the tried and true <a title="Gnu Make" href="http://www.gnu.org/software/make/">GNU Make</a> for building environments and executing tools</li>
<li>Have a "build" virtual host in every development environment for accessing the tools' web resources</li>
</ul>
<p>Using make, getting our project "enterprise" (we use space shuttle themed project names) up and running is as simple as this:</p>
<pre># clone into a directory named with your vhost name:
git clone review:enterprise.git enterprise.bshupp.dev.em.power
cd enterprise.bshupp.dev.em.power
# install into apache
make clean install</pre>
<p>&nbsp;</p>
<p>This not only provides a working application (or "shuttle" as we call them) at <em>enterprise.bshupp.dev.em.power</em>, but also a "build" virtual host for access to web resources at <em>build.enterprise.bshupp.dev.em.power</em>.  Here's a screen shot of the initial build "dashboard", which provides  navigation on the left, and some environment details and instructions on  the main page.</p>
<p><a title="dashboard by empowercampaigns, on Flickr" href="http://www.flickr.com/photos/empowercampaigns/4999009123/"><img src="http://farm5.static.flickr.com/4152/4999009123_ed3c36fae3.jpg" alt="dashboard" width="500" height="248" /></a></p>
<p>Since our web tier is in PHP, the most common tool we need to run is <a title="PHPUnit" href="http://www.phpunit.de/">PHPUnit</a>, which you run via <em>make test</em>.   You'll see the standard output in your terminal like so (with some nice  colors indicating the status - green for success and high coverage,  yellow for success and medium coverage, and red for failing tests).</p>
<p><a title="unit_tests by empowercampaigns, on Flickr" href="http://www.flickr.com/photos/empowercampaigns/4999244672/"><img src="http://farm5.static.flickr.com/4091/4999244672_d93c859ae3.jpg" alt="unit_tests" width="500" height="279" /></a></p>
<p>In addition, to view coverage details, you go to the "code coverage" link your build dashboard.</p>
<p><a title="code_coverage by empowercampaigns, on Flickr" href="http://www.flickr.com/photos/empowercampaigns/4999637302/"><img src="http://farm5.static.flickr.com/4087/4999637302_6acc299784.jpg" alt="code_coverage" width="500" height="186" /></a></p>
<p><em>make test</em> also generates <a title="TestDox" href="http://agiledox.sourceforge.net/index.html">TestDox</a> output to see which tests are failing.</p>
<p><a title="testdox by empowercampaigns, on Flickr" href="http://www.flickr.com/photos/empowercampaigns/4999637424/"><img src="http://farm5.static.flickr.com/4089/4999637424_6db759ff4c.jpg" alt="testdox" width="492" height="500" /></a></p>
<p>We keep a Selenium Remote Control (RC) server running on our  development system for easy access by developers.  Want to see if you've  broken the selenium tests?  Just run <em>make selenium-smoke</em> or <em>make selenium-full</em>, and Selenium RC will talk to your development environment.</p>
<p>And since developers need to run <em>make test selenium-smoke phpcs</em> to validate before any push to avoid breaking a build, I've wrapped them up into <em>make validate</em> for convenience.  We actually use these shortcuts with <a title="Hudson" href="http://hudson-ci.org/">Hudson</a>, which allows us to direct Selenium RC to different staging environments, or modify build steps without re-configuring Hudson.</p>
<p>Want to read the inline documentation in a web browser instead of your text editor?  Just run <em>make phpdoc</em>, then click on the "PHPDocs" link in the build dashboard.</p>
<p><a title="phpdocs by empowercampaigns, on Flickr" href="http://www.flickr.com/photos/empowercampaigns/4999216461/"><img src="http://farm5.static.flickr.com/4112/4999216461_85707fb59b.jpg" alt="phpdocs" width="500" height="271" /></a></p>
<p>One thing that's particularly useful is easy profiling with Facebook's <a title="XHProf" href="http://mirror.facebook.net/facebook/xhprof/doc.html">XHProf</a>.  Just enable profiling in your environment via <em>make enable-profiling</em>,  perform the action in the application you want to profile, then open up  the "XHProf Profiler" link in your build dashboard.  There you'll see a  list of "runs" which you can drill down into and see exactly how each  is performing.  When you're done, just run <em>make disable-profiling</em>.</p>
<p><a title="xhprof by empowercampaigns, on Flickr" href="http://www.flickr.com/photos/empowercampaigns/4999050781/"><img src="http://farm5.static.flickr.com/4126/4999050781_b561d65a53.jpg" alt="xhprof" width="500" height="271" /></a></p>
<p>To manage XHProf profile runs, I save them by environment, and wrote a  helper that allows you to browse runs by date, and then "clean" them  out when you're done.  This works easily in a shared <em>xhprof.output_dir</em> by namespacing the stored runs according to environment name.  Here is  the example snippet for starting profiling and saving as runs:</p>
<p><script src="https://gist.github.com/584952.js?file=init_profile.php"></script></p>
<p>And you can checkout the full code over on <a title="EC XHProf on Github" href="http://github.com/empower/ec_xhprof">github</a>.</p>
<p>If you want to get statistics on or content from APC, that's available too through the <a title="APC Inspector" href="http://svn.php.net/viewvc/pecl/apc/trunk/apc.php?revision=301867&amp;view=markup">inspector</a> that ships with the extension:</p>
<p><a title="apc by empowercampaigns, on Flickr" href="http://www.flickr.com/photos/empowercampaigns/4999033447/"><img src="http://farm5.static.flickr.com/4103/4999033447_71cb3df16d.jpg" alt="apc" width="500" height="282" /></a></p>
<p>Lastly, I've also included links in the dashboard to all the tools we use: our Confluence wiki, <a title="Gerrit" href="http://code.google.com/p/gerrit/">Gerrit</a>, gitweb, and Hudson.</p>
<p>This system makes it really convenient to deploy your development  environment, access documentation, profile your code, run test tools and  analyze results.  It's my hope that as our development team grows,  it'll be relatively painless to maintain high quality, well tested code.</p>
<p>Cheers,</p>
<p>Bill Shupp, Lead Developer (twitter: http://twitter.com/shupp)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2010/09/20/better-code-quality-through-easy-access-to-tools/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Importing foursquare checkins into SimpleGeo with PHP</title>
		<link>http://blog.shupp.org/2010/07/10/importing-foursquare-checkins-into-simplegeo-with-php/</link>
		<comments>http://blog.shupp.org/2010/07/10/importing-foursquare-checkins-into-simplegeo-with-php/#comments</comments>
		<pubDate>Sat, 10 Jul 2010 21:35:56 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Foursquare]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SimpleGeo]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=793</guid>
		<description><![CDATA[SimpleGeo recently blogged about exploring foursquare check-ins on a map with their service.  I'd been looking for an excuse to play with their API, so I decided to port the example in their blog (which is in python) to PHP.  Read their blog first, as it covers the process in more detail.  Just substitute their [...]]]></description>
			<content:encoded><![CDATA[<p><a title="SimpleGeo, Inc" href="http://simplegeo.com">SimpleGeo</a> recently <a title="Explore foursquare checkins with SimpleGeo" href="http://developers.simplegeo.com/blog/2010/07/09/explore-your-foursquare-checkins-on-a-map-with-simplegeo/">blogged</a> about exploring <a title="foursquare" href="http://foursquare.com">foursquare</a> check-ins on a map with their service.  I'd been looking for an excuse to play with their API, so I decided to port the example in their blog (which is in python) to PHP.  Read their blog first, as it covers the process in more detail.  Just substitute their examples with the ones below.<span id="more-793"></span></p>
<p>A broader <a title="SimpleGeo PHP Howto" href="http://simplegeo.com/docs/clients-code-libraries/php">PHP tutorial</a> for using their API is available in their documentation, but for the impatient, here's a quick install of their PHP client.  It assumes you already have a working <a href="http://pear.php.net">PEAR</a> installation:</p>
<p><code><br />
pear install HTTP_Request2-alpha<br />
pear install HTTP_OAuth-alpha<br />
pear install Net_URL2<br />
git clone git://github.com/simplegeo/Services_SimpleGeo.git<br />
cd Services_SimpleGeo<br />
pear install package.xml</code></p>
<p>And here's the actual example in PHP, which you can run from CLI:</p>
<p><script src="http://gist.github.com/471002.js?file=sg_4sq_example.php"></script></p>
<p>When running it, you should see progress:</p>
<p><code><br />
$ php sg_4sq_example.php</code><br />
<code> Sending batch 1<br />
Sending batch 2<br />
Done!<br />
</code></p>
<p>Once it's complete, go to your SimpleGeo dashboard, click on the the explorer tab for the layer you're using, and you'll see something like this, which is a history of my check-ins in San Francisco:</p>
<div id="attachment_797" class="wp-caption aligncenter" style="width: 615px"><a href="http://blog.shupp.org/wp-content/uploads/2010/07/checkins1.png"><img class="size-full wp-image-797" title="My foursquare checkins on SimpleGeo" src="http://blog.shupp.org/wp-content/uploads/2010/07/checkins1.png" alt="" width="605" height="355" /></a><p class="wp-caption-text">My local foursquare checkins on SimpleGeo</p></div>
<p style="text-align: center;">
<p style="text-align: left;">I only ran into a couple of issues with getting this working in PHP.  First, getting the right syntax for extracting the coordinates from the RSS feed took some time to get right.  I first tried with PEAR's <a href="http://pear.php.net/XML_Feed_Parser">XML_Feed_Parser</a>, but ended up just using <a href="http://php.net/SimpleXML">SimpleXML</a> directly.  Second, the blog example uses raw guid values, which break the API call when they contain a '/'.  Unfortunately, the error returned by the API was not that useful: <code>'dict' object has no attribute 'startswith'</code>.  Once I noticed the slash in the value, wrapping the guid in <code>base64_encode()</code> fixed the problem.</p>
<p style="text-align: left;">Perhaps you'll find this useful, it was fun to finally use the SimpleGeo API!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2010/07/10/importing-foursquare-checkins-into-simplegeo-with-php/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Pragmatic tips for unit testing in PHP</title>
		<link>http://blog.shupp.org/2010/02/21/pragmatic-tips-for-unit-testing-in-php/</link>
		<comments>http://blog.shupp.org/2010/02/21/pragmatic-tips-for-unit-testing-in-php/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 23:38:32 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Digg]]></category>
		<category><![CDATA[PEAR]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHPUnit]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=51</guid>
		<description><![CDATA[Recently I've been hearing a lot of differing opinions about unit testing.  Some people just don't believe in it at all, others think the value it provides is only part of the picture, and that its cost should be weighed accordingly.  Some think that 100% test coverage should be the goal for high quality software.  [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I've been hearing a lot of differing opinions about unit testing.  Some people just don't believe in it at all, others think the value it provides is only part of the picture, and that its cost should be weighed accordingly.  Some think that 100% test coverage should be the goal for high quality software.  I personally think the cost of unit testing 100% of your code is worth it, but <strong>only</strong> if you can do it efficiently.  And that's the catch; there's a learning curve to become proficient at unit testing, especially with <a title="PHPUnit" href="http://phpunit.de">PHPUnit</a>, the most prominent unit testing framework for PHP.  Unit testing should never take more than 20-30% of your overall coding time, if you do it right.<span id="more-51"></span></p>
<p>Below are some things I keep in mind when coding and testing.  I thought I'd share them here in case anyone else finds them useful.</p>
<p><strong>Think about testability when you write code, not when you write the test<br />
</strong></p>
<p>This may not be new to you, especially if you're familiar with <a title="dependency injection" href="http://en.wikipedia.org/wiki/Dependency_injection">dependency injection</a> or <a title="TDD" href="http://en.wikipedia.org/wiki/Test-driven_development">test driven development</a>.  Your unit tests should be able to run in a vacuum:  No database access, no memcache access, no headers can be sent, etc.  (Sure those things can be tested separately, but should be a small subset of your code, not the overall application logic.)  To do this, make sure you abstract those dependencies.  For example, instead of instantiating a cache driver in the middle of your method, make a getter for it which you can mock:</p>
<p><script src="http://gist.github.com/310433.js?file=gistfile1.php"></script></p>
<p>If you do this abstraction when you code, there's less refactoring to be done when writing your tests.  Also, if your dependency doesn't make a network call upon instantiation, you can still test the getter using <a title="assertType() documentation" href="http://www.phpunit.de/manual/3.4/en/api.html#api.assert.assertType">assertType()</a>.  <a title="Memcached::addServer() documentation" href="http://www.php.net/manual/en/memcached.addserver.php">Memcached's addServer()</a> is an example of such a dependency - no connection is made until you do an operation.  If this is not the case, and you can't properly test the getter, you probably want wrap the getter in <code>@codeCoverageIgnore</code> annotations like so:</p>
<p><script src="http://gist.github.com/310488.js?file=gistfile1.php"></script></p>
<p>It doesn't make sense for code you never intend to test to count against your coverage percentage.</p>
<p><strong>Keep documentation handy</strong></p>
<p>PHPUnit is a big framework.  There are a lot of things to remember, including all the assertion methods available, data providers, and mocking objects, among other things.  Rather than always copying some other example, or bugging your co-worker, spend an hour or two, and <a title="PHPUnit Documentation" href="http://www.phpunit.de/wiki/Documentation">RTFM</a>.  You'll be better off for it.  A co-worker of mine kept a printout of the <a title="TestCase docs" href="http://www.phpunit.de/manual/3.4/en/api.html#api.testcase.tables.api">PHPUnit_Framework_TestCase::getMock()</a> documentation (probably the hardest to remember) taped to his monitor.  I prefer <a title="Delicious" href="http://delicious.com/">delicious</a> bookmarking, but to each his own.  Though I've been using PHPUnit for a couple of years now, I still refer to the documentation regularly.</p>
<p><strong>Don't worry about test code re-usability</strong></p>
<p>As good OOP programmers, we are often pre-occupied with writing elegant, re-usable code, even in tests.  I have recently given up on this in my unit tests, mostly due to scope issues in PHPUnit which I'll describe later.  Rather than try consolidate re-usable code, I'm more likely to copy and paste chunks throughout my test and <strong>know</strong> that they will work.  I think the goal of tests is to write useful assertions, not necessarily elegant, re-usable components.  Why do I care how many lines are in my test code?  You might be thinking "Doesn't that make your tests harder to maintain?"  Maybe so, but in the big picture, I don't think it adds much time, and once you've fixed something in one test, then you can quickly find it elsewhere.  It might not be pretty, but it is faster, and more pragmatic, at least until the tools are better.</p>
<p><strong>Mocking scope issues</strong></p>
<p>As I mentioned above, I've found (and reported) some strange behavior I've seen with scope and mocked objects.  One pattern I see people use is a <code>getMocks()</code> helper in a test, which returns an array of commonly used objects, pre-mocked with the most used defaults already set.  Sounds like a reasonable approach to testing a large class with lots of dependency needs, right?  <strong>Wrong</strong>.  What I've found is that many times (and my test results have been inconsistent, unfortunately), you cannot modify the return value of a mocked method after its expectation has already been set.  No warning or error is thrown when you do this, but the original mocked value is returned instead of the second value you assigned.  Re-mocking return values <strong>does</strong> seem to work when it's used for throwing exceptions, though.  It appears to be a scope issue, but again, my tests have not always been consistent.  The usual result is that you spent an hour pulling your hear out trying to figure out why your test is failing.  I eventually said <em>screw it</em>, and just never set default behaviour for my mocked methods.</p>
<p>I now use a pattern where I have getters in my test for each mocked dependency, which mock each method I may need, but don't set any initial expectations yet.  I'll then pass them all into the getter for the main class I'm trying to test, which attaches them for me.  This way, on a per test basis, I set the expectations of each dependency as needed.  This seems to work much more reliably:</p>
<p><script src="http://gist.github.com/310459.js?file=gistfile1.php"></script></p>
<p><strong>Meaningful assertions</strong></p>
<p>Another complaint I hear is that, especially when enforcing code coverage rules in your development shop, developers focus more on the required coverage than on the quality of the tests.  It's important to think about what it is you're testing.  If you just call a method to make sure you get your code coverage, you're doing it wrong.  There are lots of assertions you can do:  assert the type of the response, assert the content of the response, assert the message of the exception  thrown, the exception code, the type of exception, how many times a mocked method was called, etc.  But you want to be smart about it as well.  We had one case where the original test for a Form framework was testing the exact template output.  Since there was markup and JS in the ouput, every time a designer or JS developer modified it, the test would break.  After a few breaks, I modified the test to use <a title="DomDocument documentation" href="http://www.php.net/manual/en/class.domdocument.php">DomDocument</a> parsing, and make sure the relevant form ids and attributes were present, which is really what we wanted to assert.  <strong>If you don't write meaningful tests, don't bother writing them at all.</strong></p>
<p><strong>Useful tools</strong></p>
<p>Make sure it's easy to write and run your tests.  PHPUnit has options for generating skeletons, for example, to get you started quickly.  You can use --skeleton-class to generate a class from your test (if you're practicing TDD), or the reverse, --skeleton-test, to generate a test from your class.</p>
<p>Running tests should be easy too.  One thing to keep in mind is that your include path must be correct.  For example, when I'm developing a <a title="PEAR" href="http://pear.php.net">PEAR</a> package, I may have a previous version already installed, but am developing in my repository checkout.  I need to make sure my local files are not only in my include path, but that they are at the beginning.  A handy wrapper like this should allow you to always run your development code easily:      <script src="http://gist.github.com/310504.js?file=runTests.php"></script></p>
<p>If I put this in the root of my repository, I can then call it like so:</p>
<p><code>php runTests.php --coverage-html coverage OpenID_AllTests</code></p>
<p>(If this is a PEAR package, you'll want to ignore <code>runTests.php</code> when generating your package.xml file.)</p>
<p>At Digg, our development environment tools are based on <a href="http://en.wikipedia.org/wiki/Make_%28software%29">make</a>, and it's super easy to run not only your PHPUnit tests and coverage, but also chain together running <a title="PHP_CodeSniffer" href="http://pear.php.net/package/PHP_CodeSniffer">PHP_CodeSniffer</a> for coding standards compliance:</p>
<p><code>make coverage phpcs</code></p>
<p>Facebook has a good <a title="Facebook Post on Hiring and Tools" href="http://www.facebook.com/note.php?note_id=158285241831">post</a> about hiring in general, which includes a section on <a title="Writing Tools" href="http://www.facebook.com/note.php?note_id=171746501831">writing good tools</a> for your team.  This idea certainly applies to your testing tools.  The easier you make it for your team to write good unit tests, the better.</p>
<p><strong>Conclusion</strong></p>
<p>Unit testing in PHP is not that easy, in my opinion (compared to python, anyway).  Until you get good at it, that is, and learn to work around quirks in the tools.  Then it's really not that hard.  But everyone  values unit testing differently.  If you choose to invest in testing your code, perhaps you'll find some of the above useful.   I used to not think much about unit testing, until I had a few experiences where unit tests caught problems in my code <strong>before</strong> I had run into them myself.  At this point, I think unit testing my PHP code 100% is worth it, especially now that I can do it quickly and efficiently.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2010/02/21/pragmatic-tips-for-unit-testing-in-php/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MogileFS, Zend Framework, Boobs, and Kittens</title>
		<link>http://blog.shupp.org/2010/02/10/mogilefs-zend-framework-boobs-and-kittens/</link>
		<comments>http://blog.shupp.org/2010/02/10/mogilefs-zend-framework-boobs-and-kittens/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 06:37:24 +0000</pubDate>
		<dc:creator>shupp</dc:creator>
				<category><![CDATA[Boobs]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Kittens]]></category>
		<category><![CDATA[MogileFS]]></category>
		<category><![CDATA[PEAR]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.shupp.org/?p=25</guid>
		<description><![CDATA[An upcoming side project of mine requires the use of MogileFS and Zend Framework.  MogileFS is an open source distributed file system, meant to scale up to many millions of files without a single point of failure.  It's currently used by the likes of Digg and last.fm. Though I was already familiar with using MogileFS [...]]]></description>
			<content:encoded><![CDATA[<p>An upcoming side project of mine requires the use of <a title="MogileFS" href="http://www.danga.com/mogilefs/">MogileFS</a> and <a title="Zend Framework" href="http://framework.zend.com">Zend Framework</a>.  MogileFS is an open source distributed file system, meant to scale up to many millions of files without a single point of failure.  It's currently used by the likes of <a title="Digg" href="http://digg.com">Digg</a> and <a title="last.fm" href="http://last.fm">last.fm</a>.</p>
<p>Though I was already familiar with using MogileFS clients in <a title="File_Mogile" href="http://pear.php.net/package/file_mogile/redirected">php</a> and <a href="http://www.albany.edu/~ja6447/mogilefs.py">python</a> at work, the operations team actually runs the servers.   I wanted to get some experience with managing MogileFS itself (trackers, mogstored, mysql), and hopefully have a better understanding of how it all worked together.  While I was already familiar with Zend Framework, I'd never used it to serve images.  So, I figured I should build a quick prototype using both.  But what to build?  I decided to take inspiration from the notorious <a title="Explosions and Boobs" href="http://explosionsandboobs.com">http://explosionsandboobs.com</a>, but put my own spin on it.  The result?</p>
<p><a href="http://boobsandkittens.com">http://boobsandkittens.com</a><span id="more-25"></span></p>
<p>Bear in mind that the above URL is on my inexpensive <a title="Slicehost" href="http://slicehost.com">Slicehost</a> VPS, and can be slow at times.  This is a really simple application that allowed me to do a few things:</p>
<ul>
<li>scrape some content from google images search</li>
<li>store them in MogileFS</li>
<li>render the stored images through ZF</li>
</ul>
<p>The source is available <a title="Boobs and Kittens Source" href="http://github.com/shupp/bandk">here</a>.  The <a title="google images scraper" href="http://github.com/shupp/bandk/blob/master/application/cli/scrape.php">scraper</a> is pretty straight forward.  I just called it from the command line to save images to a directory.  Once saved to disk, I used the <a title="mogrify" href="http://www.imagemagick.org/script/mogrify.php">mogrify</a> tool from Imagemagick to scale the images down to a height of 400 px max, and visually removed the worst of the images (it's relatively SFW).  Next, I inserted those images into MogileFS with <a title="insertImage.php" href="http://github.com/shupp/bandk/blob/master/application/cli/insertImage.php">insertImage.php</a>.  There are only two real action controllers, the <a href="http://github.com/shupp/bandk/blob/master/application/controllers/IndexController.php">index page</a> and <a href="http://github.com/shupp/bandk/blob/master/application/controllers/ImageController.php">image renderer</a>.  The latter was really the only thing to learn on the php side of this project.  The key there was disabling the layout and view rendering, as well as setting the appropriate image information in the response object (content-type, content-length, and the content itself).  Since most of the logic is in the <a href="http://github.com/shupp/bandk/blob/master/application/models/Model/Images.php">model</a>, the action controllers are pretty skinny.  I used memcache to store db queries and the images from MogileFS to help offset the performance of a cheap VPS.  Since Zend Framework doesn't ship with a MogileFS client, I used the <a href="http://pear.php.net/package/file_mogile/redirected">PEAR</a> one.</p>
<p>That's it.  Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.shupp.org/2010/02/10/mogilefs-zend-framework-boobs-and-kittens/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

