<?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>Digital Sandwich</title>
	<atom:link href="http://digitalsandwich.com/feed" rel="self" type="application/rss+xml" />
	<link>http://digitalsandwich.com</link>
	<description>Forever Proving I am a Geek</description>
	<lastBuildDate>Sun, 01 Jan 2012 23:58:31 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Phake 1.0.0 is finished</title>
		<link>http://digitalsandwich.com/archives/100-phake-1-0-0-is-finished.html</link>
		<comments>http://digitalsandwich.com/archives/100-phake-1-0-0-is-finished.html#comments</comments>
		<pubDate>Sun, 01 Jan 2012 23:57:27 +0000</pubDate>
		<dc:creator>Mike Lively</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP Testing]]></category>
		<category><![CDATA[phake]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://digitalsandwich.com/?p=100</guid>
		<description><![CDATA[So, now that 2012 is here, I can confidently say that I have accomplished two things&#8230;the first is proving that I can indeed completely neglect my site for a year. The second is that given a free weekend I can &#8230; <a href="http://digitalsandwich.com/archives/100-phake-1-0-0-is-finished.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[
<p>So, now that 2012 is here, I can confidently say that I have accomplished two things&#8230;the first is proving that I can indeed completely neglect my site for a year. The second is that given a free weekend I can still finish things. I just got done rolling the 1.0.0 stable release of <a href="http://phake.digitalsandwich.com/?p=59" title="Phake">Phake</a>.</p>
<p>I spent the better part of yesterday and today working out the last of the kinks and I am pretty happy with the results. It provides a great alternative mocking framework for PHPUnit that is compatible not just with older versions of PHPUnit but also older versions of PHP (5.2). You can look through my blog for some of my initial posts about it, or you can peruse the<a href="http://phake.digitalsandwich.com/docs/html/"> Phake documentation</a>. It allows you to do quite a few nifty things.</p>
<p>A big thanks to all those who have contributed feedback / code thus far.</p>
<p>Happy new year!</p>

]]></content:encoded>
			<wfw:commentRss>http://digitalsandwich.com/archives/100-phake-1-0-0-is-finished.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Pear Channel set up for Phake</title>
		<link>http://digitalsandwich.com/archives/93-pear-channel-set-up-for-phake.html</link>
		<comments>http://digitalsandwich.com/archives/93-pear-channel-set-up-for-phake.html#comments</comments>
		<pubDate>Fri, 31 Dec 2010 05:52:28 +0000</pubDate>
		<dc:creator>Mike Lively</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP Testing]]></category>
		<category><![CDATA[phake]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phpunit]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://digitalsandwich.com/?p=93</guid>
		<description><![CDATA[For those that may not have caught my first post on the subject, Phake is a mock framework that I announced a couple of days ago in Introducing Phake Mocking Framework. It was recommended in the comments that I get &#8230; <a href="http://digitalsandwich.com/archives/93-pear-channel-set-up-for-phake.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[
<p>For those that may not have caught my first post on the subject, <a href="https://github.com/mlively/Phake">Phake</a> is a mock framework that I announced a couple of days ago in <a href="http://digitalsandwich.com/archives/84-introducing-phake-mocking-framework.html">Introducing Phake Mocking Framework</a>. It was recommended in the comments that I get it on a pear channel somewhere, which is something I have wanted to do but hadn&#8217;t had a reason to do until this week. Well, now there is an official <a href="http://pear.digitalsandwich.com/">Digital Sandwich Pear Channel</a> that is hosting Phake. So if you want to play around with Phake you can install it like this:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">pear channel-discover pear.digitalsandwich.com<br />
pear install channel://pear.digitalsandwich.com/Phake-1.0.0alpha</div></div>
<p>Also, a couiple quick little side notes, the only reason I am still considering this an alpha is the lack of exhaustive, centralized documentation. The <a href="https://github.com/mlively/Phake/wiki">Phake Wiki</a> has some good details as does my previous post but I would like to get more official documentation up soon at which put it into a full beta. The api right now should be considered stable however. It will not be changing short of huge issues. We have been using it in production testing at my company for a little while no with great success. So, if the label of &#8216;alpha&#8217; makes you nervous, don&#8217;t worry. It&#8217;ll be okay.</p>
<p>Lastly, this library is compatible with PHP 5.2. I never really mentioned that in my last post either. It is not currently utilizing any php 5.3 functionality and I have no plans to break this backwards compatibility any time soon.</p>

]]></content:encoded>
			<wfw:commentRss>http://digitalsandwich.com/archives/93-pear-channel-set-up-for-phake.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Introducing Phake Mocking Framework</title>
		<link>http://digitalsandwich.com/archives/84-introducing-phake-mocking-framework.html</link>
		<comments>http://digitalsandwich.com/archives/84-introducing-phake-mocking-framework.html#comments</comments>
		<pubDate>Wed, 29 Dec 2010 06:22:13 +0000</pubDate>
		<dc:creator>Mike Lively</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP Testing]]></category>
		<category><![CDATA[phake]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phpunit]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://digitalsandwich.com/?p=84</guid>
		<description><![CDATA[I have used PHPUnit heavily now for the last 4 years. As anyone that is heavily involved in writing Unit Tests knows, test doubles (commonly referred to as mock objects) are a necessary part of your toolbox. The mocking options &#8230; <a href="http://digitalsandwich.com/archives/84-introducing-phake-mocking-framework.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[
<p>I have used PHPUnit heavily now for the last 4 years. As anyone that is heavily involved in writing Unit Tests knows, test doubles (commonly referred to as mock objects) are a necessary part of your toolbox. The mocking options that we used to have for PHP unit testing have traditionally been fairly limited and most all of them in some form or another were ports of <a href="http://www.jmock.org/jmock1-getting-started.html">JMock</a>. The way PHP operates as well as some decisions made to more closely emulate how JMock does things lead to functionality in the existing mock library for PHPUnit that for some are a hassle. This ranges from PHPUnit implicitly calling the &#8220;mockee&#8217;s&#8221; constructor (you have to explicitly specify that you do not want to call the constructor) to the pain of trying to stub or verify multiple invocations of the same method with different parameters.</p>
<p>Over the last three years, my experience as well as the musing of some of my colleagues has led me to believe that a lot of what I don&#8217;t like about mocking in php is the result of the fundamental notions of combining stubbing with verification and setting expectations ahead of method calls instead of verifying that what you expected to happen has indeed happened. This was essentially proven to me over the last year and a half as I have been heavily working with Java code and as a result have been using the <a href="http://mockito.org/">Mockito</a> mocking library for Java. The result of this work is the <a href="https://github.com/mlively/Phake">Phake Mocking Framework</a>.</p>
<p>Now I am fairly certain that at least 5 or 6 people (which may constitute everyone who reads this) are rolling their eyes by now. So instead of going further into why I like this style of mocking I&#8217;ll just show you how to use it. Phake was designed with PHPUnit in mind, however I don&#8217;t really see any reason why it couldn&#8217;t be used in other testing frameworks as well. It is on my roadmap to confirm support for other frameworks. In any case, I will be using PHPUnit for my examples.</p>
<p>This document assumes you already have a good understanding of the basics of mocking. If the terms &#8216;Mocking&#8217;, &#8216;Stubbing&#8217;, and &#8216;Test Doubles&#8217; mean nothing to you, I would recommend checking out the following links:</p>
<ul>
<li><a href="http://www.phpunit.de/manual/current/en/test-doubles.html">PHPUnit on Mock Objects</a></li>
<li><a href="http://en.wikipedia.org/wiki/Mock_object">Wikipedia on Mock Objects</a></li>
<li><a href="http://www.google.com/search?client=ubuntu&#038;channel=fs&#038;q=What+are+Mock+Objects%3F&#038;ie=utf-8&#038;oe=utf-8">The Universe on Mock Objects</a></li>
</ul>
<h2>Getting Started</h2>
<p>You can get a copy of <a href="https://github.com/mlively/Phake">Phake</a> from Github. If you are familiar and comfortable with with git you can just clone my repository. If you would rather avoid the trappings of Github, you can also download <a href="https://github.com/mlively/Phake/tarball/latest">Phake&#8217;s latest release tarball</a>. Either way will result in a directory with two subdirectories: src and test. You will want to move the contents of the src directory to somewhere in your include path (such as /usr/share/php). Once you have done this, you can simply include &#8220;Phake.php&#8221; in any of your tests or in your bootstrap script and you will be off to the races.</p>
<hr />
<h3>UPDATE!!!</h3>
<p>I just set up a pear channel to distribute phake as well. So if you would like to install Phake using pear, just do the following:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">pear channel-discover pear.digitalsandwich.com<br />
pear install channel://pear.digitalsandwich.com/Phake-1.0.0alpha</div></div>
<hr />
<p>To show you some of the basics of how to use this framework, I am going to write various bits of codes to mock, verify, stub, etc the following class:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> MyClass<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$value</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">value</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$value</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getValue<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">value</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> subtract<span style="color: #009900;">&#40;</span><span style="color: #000088;">$int</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">value</span> <span style="color: #339933;">-</span> <span style="color: #000088;">$int</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">?&gt;</span></div></div>
<h2>Stubbing</h2>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
<br />
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'Phake.php'</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">class</span> Test <span style="color: #000000; font-weight: bold;">extends</span> PHPUnit_Framework_TestCase<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testStubbingGetValue<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Sets up the mock object.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Analogous to $this-&gt;getMock() in PHPUnit</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span> <span style="color: #339933;">=</span> Phake<span style="color: #339933;">::</span><span style="color: #004000;">mock</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MyClass'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Builds the stub for getValue. </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Essentially any call to getValue will return 42</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Phake<span style="color: #339933;">::</span><span style="color: #004000;">when</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">thenReturn</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #339933;">,</span> <span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>You can also do conditional stubbing based on passed in parameters.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testStubbingGetValue2<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span> <span style="color: #339933;">=</span> Phake<span style="color: #339933;">::</span><span style="color: #004000;">mock</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MyClass'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// You can pass parameters into the stubbed method to indicate you</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// only want to stub matching invocations. By default, anything </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// passed in must be loosely matched ('==')</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Phake<span style="color: #339933;">::</span><span style="color: #004000;">when</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">thenReturn</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #339933;">,</span> <span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// It is important to note that any unstubbed calls will return null.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Since 41 != 42 this call will return null.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertNull</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">41</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>If a specific invocation or call of a mock object has not been stubbed, it will return null. This behavior is different than the default behavior of PHPUnit&#8217;s mocking framework. If you need the default PHPUnit behavior then you could use something called partial mocks. Partial mocks are setup to call the constructor of the class being mocked and for any call that has not been stubbed, the parent method will be called.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testStubbingGetValue3<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Creates a mock object whose constructor will call </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// MyClass::__construct(42);</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span> <span style="color: #339933;">=</span> Phake<span style="color: #339933;">::</span><span style="color: #004000;">partMock</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MyClass'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; Phake<span style="color: #339933;">::</span><span style="color: #004000;">when</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">thenReturn</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Since 18 != 42, the real method gets call </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">24</span><span style="color: #339933;">,</span> <span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">18</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>You can also specify on a per call basis that you want to call the parent, using the thenCallParent() method instead of thenReturn(). The different values you can use for stubbing are referred to as &#8216;Answers&#8217;. Here are a list of them and what they will do when a matching invocation is called:</p>
<ul>
<li><strong>thenReturn(mixed $var)</strong> &#8211; Will return the exact value passed in.</li>
<li><strong>thenCallParent()</strong> &#8211; Will return the results of calling the mocked parent method.</li>
<li><strong>thenThrow(Exception $e)</strong> &#8211; Will throw $e.</li>
<li><strong>captureReturnTo(&#038;$variable)</strong> &#8211; Acts exactly like thenCallParent() however it also captures the value that the parent returned to $variable. This allows you to run assertions. This comes in very handy for testing legacy code with protected or private factory methods whose return values are never returned out of the tested method&#8217;s scope.</li>
</ul>
<p>The other thing to take note of stubbing is that any PHPUnit constraints are supported.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testStubbingGetValue4<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span> <span style="color: #339933;">=</span> Phake<span style="color: #339933;">::</span><span style="color: #004000;">mock</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MyClass'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//Matches any call to subtract() where the passed in value equals 42</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Phake<span style="color: #339933;">::</span><span style="color: #004000;">when</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">thenReturn</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//Matches any call to subtract() where the passed in value is less </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// than 42. Notice that this is a phpunit constraint</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Phake<span style="color: #339933;">::</span><span style="color: #004000;">when</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lessThan</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">thenReturn</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">29</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">30</span><span style="color: #339933;">,</span> <span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">29</span><span style="color: #339933;">,</span> <span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">41</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>This gives you the same kind of stubbing flexibility that you have present in PHPUnit.</p>
<h2>Verification</h2>
<p>Verifying that methods on your stub are called is starkly different then how it is done in PHPUnit. The most apparent symptom of this difference is that you verify calls <em>after</em> the calls to your test methods have been made.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testVerify1<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// You can apply stubbings and verifications to the same mock objects</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span> <span style="color: #339933;">=</span> Phake<span style="color: #339933;">::</span><span style="color: #004000;">mock</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MyClass'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//Notice, getValue() has already been called</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Phake<span style="color: #339933;">::</span><span style="color: #004000;">verify</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>You of course have the same matching functionality at your disposal.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testVerify2<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span> <span style="color: #339933;">=</span> Phake<span style="color: #339933;">::</span><span style="color: #004000;">mock</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MyClass'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">40</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//Notice the constraint</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Phake<span style="color: #339933;">::</span><span style="color: #004000;">verify</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lessThan</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>By default, verify only allows a single matching invocation. You can also specify that a specific number of invocations should be allowed.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testVerify3<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span> <span style="color: #339933;">=</span> Phake<span style="color: #339933;">::</span><span style="color: #004000;">mock</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MyClass'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">40</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">39</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//The number of times is passed as the second parameter of </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//Phake::verify()</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Phake<span style="color: #339933;">::</span><span style="color: #004000;">verify</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mock</span><span style="color: #339933;">,</span> Phake<span style="color: #339933;">::</span><span style="color: #004000;">times</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lessThan</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>You can also use Phake::atLeast($n) and Phake::atMost($n) instead of Phake::times($n).</p>
<p>You can also specify that you don&#8217;t expect there to be any interactions with a mock.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testVerify4<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span> <span style="color: #339933;">=</span> Phake<span style="color: #339933;">::</span><span style="color: #004000;">mock</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MyClass'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// This will ensure that UP TO THIS POINT no methods on $mock have </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// been called</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Phake<span style="color: #339933;">::</span><span style="color: #004000;">verifyNoInteraction</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// This would not result in an error, this can be prevented with </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// another method explained below</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>I am sure you noticed the comment that Phake::verifyNoInteraction() only verifies that no calls were made up to that point. You can essentially <em>freeze</em> a mock with another method</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testVerify5<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span> <span style="color: #339933;">=</span> Phake<span style="color: #339933;">::</span><span style="color: #004000;">mock</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MyClass'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// This will ensure that no methods on $mock will be called after this </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// point</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Phake<span style="color: #339933;">::</span><span style="color: #004000;">verifyNoFurtherInteraction</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>There are a few more advanced things you can do with something called argument captors.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> testVerify6<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span> <span style="color: #339933;">=</span> Phake<span style="color: #339933;">::</span><span style="color: #004000;">mock</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MyClass'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$mock</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Phake::capture tells Phake to store the parameter passed to </span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// subtract as the variable $val</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Phake<span style="color: #339933;">::</span><span style="color: #004000;">verify</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$mock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">subtract</span><span style="color: #009900;">&#40;</span>Phake<span style="color: #339933;">::</span><span style="color: #004000;">capture</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$val</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">assertEquals</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #339933;">,</span> <span style="color: #000088;">$val</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>This is a very pedestrian example, but it is not that uncommon for fairly complicated objects to passed in and out of methods. Argument capturing allows you to much more succinctly assert the state of those types of parameters. It is definitely overkill for asserting scalar types or simple objects.</p>
<h2>More to Come</h2>
<p>This really does cover the very basics of the Phake framework. In the coming days I will be putting out smaller more focused articles discussing some of the specific functionality. In the meantime I would love to get some feedback from anyone who is brave enough to play with this. My future roadmap basically involves shoring up the current code base a little bit more, adding a few pieces of missing or suboptimal functionality (I&#8217;m not so sure I have implemented &#8216;consecutive calls&#8217;) but I anticipate releasing an RC version no later than the end of January. Also, I am currently using and monitoring the <a href="https://github.com/mlively/Phake/issues">issue tracker for Phake</a> at github, so if you have some functionality you would like or find any bugs in your exploring, you can also open an issue there. Also, if you would like to help out with contributions, they are certainly welcome.</p>

]]></content:encoded>
			<wfw:commentRss>http://digitalsandwich.com/archives/84-introducing-phake-mocking-framework.html/feed</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>YAML Now Supported by PHPUnit Database Extension</title>
		<link>http://digitalsandwich.com/archives/79-yaml-now-supported-by-phpunit-database-extension.html</link>
		<comments>http://digitalsandwich.com/archives/79-yaml-now-supported-by-phpunit-database-extension.html#comments</comments>
		<pubDate>Sun, 01 Feb 2009 18:22:13 +0000</pubDate>
		<dc:creator>Mike Lively</dc:creator>
				<category><![CDATA[PHP Testing]]></category>

		<guid isPermaLink="false">http://digitalsandwich.com/?p=79</guid>
		<description><![CDATA[I have now just committed YAML data sets to the Database Extension for PHPUnit. So now all those that love the simplicity and straightforwardness of YAML can use it with your data sets. I have also created a persistor for &#8230; <a href="http://digitalsandwich.com/archives/79-yaml-now-supported-by-phpunit-database-extension.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[
<p>I have now just committed <a href="http://yaml.org/">YAML</a> data sets to the Database Extension for <a href="http://www.phpun.it">PHPUnit</a>. So now all those that love the simplicity and straightforwardness of YAML can use it with your data sets. I have also created a persistor for YAML datasets so you can easily convert existing data sets or database data into YAML representations.</p>
<p>This is really the first I have dealt with YAML and it is definitely a viable alternative for data sets. Here is what they will look like.</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">table1:<br />
&nbsp; -<br />
&nbsp; &nbsp; table1_id: 1<br />
&nbsp; &nbsp; columnName1: &quot;tgfahgasdf&quot;<br />
&nbsp; &nbsp; columnName2: 200<br />
&nbsp; &nbsp; columnName3: 34.64<br />
&nbsp; &nbsp; columnName4: yghkf;a &nbsp;hahfg8ja h;<br />
table2:<br />
&nbsp; -<br />
&nbsp; &nbsp; table2_id: 1<br />
&nbsp; &nbsp; column5: fhah<br />
&nbsp; &nbsp; column6: 456<br />
&nbsp; &nbsp; column7: 46.5<br />
&nbsp; &nbsp; column8: &quot;fsdb, ghfdas&quot;<br />
&nbsp; -<br />
&nbsp; &nbsp; table2_id: 3<br />
&nbsp; &nbsp; column5: ajsdlkfguitah<br />
&nbsp; &nbsp; column6: 654<br />
&nbsp; &nbsp; column7: blah<br />
&nbsp; &nbsp; column8: |-<br />
&nbsp; &nbsp; &nbsp; thesethasdl<br />
&nbsp; &nbsp; &nbsp; asdflkjsadf asdfsadfhl &quot;adsf, halsdf&quot; sadfhlasdf</div></div>
<p>The biggest issue I had was figuring out how YAML dealt with trailing line breaks. It appears that &#8216;|-&#8217; did the trick. It will strip the final line break. Another thing to take note is that indention is important. It doesn&#8217;t HAVE to be spaces (it can be tabs) it just needs to be consistent. The last thing is that strings do not need to be quoted, but if they are you can use escape characters (like \n.)</p>
<p>This was committed to the trunk of PHPUnit and I anticipate Sebastian will be merging it back into 3.4 shortly.</p>

]]></content:encoded>
			<wfw:commentRss>http://digitalsandwich.com/archives/79-yaml-now-supported-by-phpunit-database-extension.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Improved PHPUnit Filters</title>
		<link>http://digitalsandwich.com/archives/78-improved-phpunit-filters.html</link>
		<comments>http://digitalsandwich.com/archives/78-improved-phpunit-filters.html#comments</comments>
		<pubDate>Sun, 01 Feb 2009 04:54:28 +0000</pubDate>
		<dc:creator>Mike Lively</dc:creator>
				<category><![CDATA[PHP Testing]]></category>

		<guid isPermaLink="false">http://digitalsandwich.com/?p=78</guid>
		<description><![CDATA[I have finally gotten some time to do some long awaited work on PHPUnit. The first on my agenda was a small improvement to filtering. This was related to ticket #526. Essentially I added the ability to do both white &#8230; <a href="http://digitalsandwich.com/archives/78-improved-phpunit-filters.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[
<p>I have finally gotten some time to do some long awaited work on PHPUnit. The first on my agenda was a small improvement to filtering. This was related to <a href="http://www.phpunit.de/ticket/526">ticket #526</a>. Essentially I added the ability to do both white list and black list filtering.
</p>
<p>For instance, if you wanted to specify an include filter you can do the following:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <br />
<span style="color: #666666; font-style: italic;">//... </span><br />
<br />
<span style="color: #000088;">$filteredDataSet</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PHPUnit_Extensions_Database_DataSet_DataSetFilter<span style="color: #009900;">&#40;</span><span style="color: #000088;">$dataSet</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000088;">$filteredDataSet</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addIncludeTables</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table1'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'table3'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<span style="color: #000088;">$filteredDataSet</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setIncludeColumnsForTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table1'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'column1'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'column2'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'column3'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'column4'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<span style="color: #000088;">$filteredDataSet</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setIncludeColumnsForTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table3'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'column9'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'column10'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'column11'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'column12'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">//... </span><br />
<span style="color: #000000; font-weight: bold;">?&gt;</span></div></div>
<p>I have also deprecated passing the filter to the constructor. The reason for this is that I would like to begin adding a few more features to the filter and the current method of passing the parameters on the constructor would be unintuitive for these planned features. Basically I think it was a mistake for me to allow the passing of filter data on the constructor to begin with. I anticipate the current method working up to PHPUnit 4.0 but it will not be expanded on and will be removed either in PHPUnit 4 or in a release soon after that.
</p>
<p>So, for exclude filters, instead of specifying them in the constructor, the new method will be:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <br />
<span style="color: #666666; font-style: italic;">//...</span><br />
<br />
<span style="color: #000088;">$filteredDataSet</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PHPUnit_Extensions_Database_DataSet_DataSetFilter<span style="color: #009900;">&#40;</span><span style="color: #000088;">$dataSet</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000088;">$filteredDataSet</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addExcludeTables</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table2'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<span style="color: #000088;">$filteredDataSet</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setExcludeColumnsForTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table1'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table1_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<span style="color: #000088;">$filteredDataSet</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setExcludeColumnsForTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table3'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table3_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">//... </span><br />
<span style="color: #000000; font-weight: bold;">?&gt;</span></div></div>
<p>While you can&#8217;t mix include and exclude filters for tables (wouldn&#8217;t make sense right now) you CAN do this for table columns of separate tables:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <br />
<span style="color: #666666; font-style: italic;">//...</span><br />
<br />
<span style="color: #000088;">$filteredDataSet</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PHPUnit_Extensions_Database_DataSet_DataSetFilter<span style="color: #009900;">&#40;</span><span style="color: #000088;">$dataSet</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000088;">$filteredDataSet</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addIncludeTables</span><span style="color: #009900;">&#40;</span><a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table1'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'table3'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<span style="color: #000088;">$filteredDataSet</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setExcludeColumnsForTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table1'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table1_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<span style="color: #000088;">$filteredDataSet</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setIncludeColumnsForTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table3'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'column9'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'column10'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'column11'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'column12'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;">//... </span><br />
<span style="color: #000000; font-weight: bold;">?&gt;</span></div></div>
<p>Some future features I plan on adding include, global column includes/excludes and wild cards. Anyhow, hope this is useful for someone.</p>

]]></content:encoded>
			<wfw:commentRss>http://digitalsandwich.com/archives/78-improved-phpunit-filters.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Why I Hate Singletons</title>
		<link>http://digitalsandwich.com/archives/77-why-i-hate-singletons.html</link>
		<comments>http://digitalsandwich.com/archives/77-why-i-hate-singletons.html#comments</comments>
		<pubDate>Tue, 23 Dec 2008 16:12:40 +0000</pubDate>
		<dc:creator>Mike Lively</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://digitalsandwich.com/?p=77</guid>
		<description><![CDATA[One of the most derided, yet most loved and used patterns is the singleton pattern. Its supporters continually praise its ability to limit instantiation of objects and its opponents continually chastise its tendency to be little more than a glorified &#8230; <a href="http://digitalsandwich.com/archives/77-why-i-hate-singletons.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[
<p>
One of the most derided, yet most loved and used patterns is the singleton pattern. Its supporters continually praise its ability to limit instantiation of objects and its opponents continually chastise its tendency to be little more than a glorified global.
</p>
<p>
While programming in many ways boils down to a matter of preference (you can always find someone that agrees with you,) I thought I might as well document my opinion so that those who don&#8217;t care can have one more thing to ignore.
</p>
<p>Details after the jump</p>
<p><span id="more-77"></span></p>
<p>
First, what is the singleton? Most of us know what it is and for many of us I would guess it is the first pattern we grew to know and love. The official definition from the GoF&#8217;s book is as follows.
</p>
<p><i><br />
Ensure a class only has one instance and provide a global point of access to it.</i> <b>- <a href="http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612">Design Patterns: Elements of Reusable Object-Oriented Software.</a></b>
</p>
<p>
The basic summary of why I think singletons are evil is summed up in the second half of its definition. It provides a &quot;global point of access&quot;. Even people that say singletons are not evil tend to ignore the fact that this is a built in property of the pattern and some even go so far as to not realize that this is even mentioned in the official definition:
</p>
<p>
<i>Singletons should be used to control creation, not access. A singleton should *not* be used as a global object just because you can. I find it hard to dismiss a pattern simply because some people don&#8217;t use it how it was intended to be used.</i> <b>- Matt Berther, <a href="http://www.mattberther.com/2004/05/27/singletons-are-not-evil/">Singletons are not evil</a></b></p>
<p>
A large, defined purpose of the singleton is to provide a global point of access to an object. This cannot be argued.
</p>
<h3>So why is a single point of access a bad thing?</h3>
<p>
A single point of access is not in and of itself a bad thing. If you read the entirety of Matt Berther&#8217;s article, you would find that he is very clear that he does not believe you should use a singleton as a global just because you can. By &quot;using it as a global&quot; he is referring to the method of peppering your code with calls to MySingleton::getInstance(). It may be hard to see some of the initial similarities between the following snippets of code.
</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp;</div></div>
<p>and</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp;</div></div>
<p>
Don&#8217;t let the extra class name fool you. While it does indeed force that object to be of a particular class you will never have any clue by looking strictly at your method declaration of what the dependencies of the method are. This is one of the large problems with both globals and singletons: they mask your dependencies. This will without a doubt make your code less flexible and harder to understand. The lack of flexibility also makes your code harder to test and in the long run harder to maintain.
</p>
<h3>But the singleton pattern is so useful!</h3>
<p>
Of course singletons are useful. There are many things that are <a href="http://failblog.org/2008/01/31/not-long-now/">useful</a>, but that doesn&#8217;t automatically make it a good idea.</p>
<p> I will admit, I have used singletons quite heavily in my past. The most common reasons that I would implement them are:</p>
<ol>
<li>You can only legitimately have one logical instance of a class</li>
<li>The object is expensive to create</li>
<li>You need primitive caching (sort of related to #2)</li>
</ol>
<p>
These are all legitimate reasons to use a singleton pattern. I would discourage the thought of using as a permanent solution for caching however. While it is useful for quick and dirty caching there are many more useful patterns and systems for doing this.
</p>
<p>
So if you take away caching then there are still two uses for the singleton. A responsible person does not tell you to not use something without offering an alternative. So here is my alternative:
</p>
<h3>Don&#8217;t use singletons&#8230;</h3>
<p>
That&#8217;s right, sage advice I know. If your software is designed properly you should still be able to centralize the object creation (that needs centralized) to ensure that you only are creating one instance of an object. If you need to control creation of it then use a factory to do so. Then pass the object to the methods that need it. This will allow you to make your dependencies much more explicit which will provide you with more flexibility in the long run. It will also allow you to unit test your code much more effectively.
</p>
<h3>Unless you have to!</h3>
<p>
There are some times you just cannot get away from singletons. In most cases the reason why is the amount of refactoring that it would involve. You simply do not have time for it. The singleton pattern is not all bad. I do think it is a viable pattern for object creation. So just don&#8217;t &quot;take advantage&quot; of the second half of its definition (global access.) Get rid of all the getInstance() calls. Those are the real problem with singletons anyways. Move them as high in your call chain as you possibly can. Then you get the benefits of NOT using the singleton without having to embark on a massive rewrite of code.
</p>
<h3>I bid you farewell</h3>
<p>
Ultimately, programming is a matter of preference. So long as you are achieving easy to understand and therefore easy to maintain code. It doesn&#8217;t honestly matter much how you do it. I personally do not see very many viable uses for singletons and I know there are many people that agree with me (google <a href="http://www.google.com/search?q=evil+singletons">evil singletons</a>). It&#8217;s simplicity seems appealing, but they are incredibly easy to use in a damaging way. This is the danger you risk with any concept that is easy to understand <b>and</b> easy to abuse.</p>

]]></content:encoded>
			<wfw:commentRss>http://digitalsandwich.com/archives/77-why-i-hate-singletons.html/feed</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
		<item>
		<title>Book Review: PHP5 CMS Framework Development by Martin Brampton</title>
		<link>http://digitalsandwich.com/archives/76-book-review-php5-cms-framework-development-by-martin-brampton.html</link>
		<comments>http://digitalsandwich.com/archives/76-book-review-php5-cms-framework-development-by-martin-brampton.html#comments</comments>
		<pubDate>Thu, 11 Dec 2008 08:22:00 +0000</pubDate>
		<dc:creator>Mike Lively</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://digitalsandwich.com/?p=76</guid>
		<description><![CDATA[PHP5 CMS Framework Development (published by packt publishing) is a a book that offers &#34;Expert insight and practical guidance to creating an efficient, flexible, and robust framework for a PHP5 based content management system.&#34; Upon reading through the book I &#8230; <a href="http://digitalsandwich.com/archives/76-book-review-php5-cms-framework-development-by-martin-brampton.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[
<p><a href="http://www.packtpub.com/PHP-5-CMS-Framework-Development/book/mid/2705088rxarn">PHP5 CMS Framework Development</a> (published by <a href="http://www.packtpub.com">packt publishing</a>) is a a book that offers &quot;Expert insight and practical guidance to creating an efficient, flexible, and robust framework for a PHP5 based content management system.&quot; Upon reading through the book I have found that it gives an excellent case study of <a href="http://martinbrampton.com/">Martin Brampton&#8217;s</a> approach to CMS design and implementation. Brampton has been very active in the PHP CMS scene for several years working on widely known projects such as Mambo and Joomla. He is also the creator of Aliro, a newer CMS that had the purpose of utilizing more of the object oriented abilities of PHP5. His experience designing and developing Aliro influenced much of this book.</p>
<p>One might be concerned that the ideas in this book are slanted towards how Brampton decided to implement various aspects of Aliro. While it is true that much of the book uses code directly out of Aliro, I feel that he did take the time to make sure he explained the reasons for the design and development decisions he made. This is the feeling that brings me to the overall conclusion that this book is ultimately an in depth case study of the design of Aliro. If you are interested in developing your own CMS framework or have already developed a framework that you would like to extend, then I would highly recommend this book. Even if you do not agree with all of the concepts and ideas presented it does a fantastic job at pointing out potential pitfalls and other items to consider as you work on your CMS.</p>
<p>After the jump I give a chapter by chapter breakdown of the book.</p>
<p><span id="more-76"></span><br />
The book begins with a general description of what Brampton deems as<br />
generic features of a CMS. He takes time to discuss both what he<br />
considers critical features (user management, access control, security<br />
and extensibility) and what he considers to be &quot;desirable&quot; features:<br />
(performance, database abstraction, menuing, and<br />
internationalization/localization.) He then goes on to make a good case<br />
for why PHP 5 should be used. In some senses I find it disheartening<br />
that after several years we are still trying to sell PHP 5 but this is<br />
certainly not Brampton&#8217;s fault. He also briefly addresses some basic<br />
best practices for php development. Some of the ideas he presents in<br />
this chapter I do not completely agree with. The promotion of<br />
singletons is something that always disheartens me as I am still<br />
convinced that they are heavily overused in the programming world.<br />
Brampton also promotes the use of HEREDOCS which I have grown to<br />
dislike for mostly stylistic reasons. He does however make excellent<br />
point about the importance of considering certain patterns for use in<br />
development with particular attention towards the MVC pattern.</p>
<p>After<br />
giving a one chapter intro to the basics of CMS design Brampton dives<br />
into studies of various, common aspects of CMS systems. I appreciate<br />
the basic organization of each of these sections. Each chapter starts<br />
off briefly describing a common problem. Then a more detailed analysis<br />
of the problem commences covering various aspects of the problem domain<br />
to consider. After presenting various view points and ideas he<br />
concludes the chapter with the solution he chose. The solutions are<br />
detailed at a very low level including both code and often a database<br />
schema as well. Great care is taken to ensure that the solution<br />
addresses in some form or another each aspect of the problem. The<br />
beauty of this organization is that it allows you to more easily use<br />
this book as a reference when you do hit a road block. It offers the<br />
ability to get another opinion and more ideas on the problem you are<br />
trying to solve.</p>
<p>In chapter two Brampton begins addressing the<br />
various aspects of CMS frameworks in more detail. This chapter deals<br />
with user management in a CMS. It covers several different areas of<br />
user management including storing and securing user data,<br />
authenticating users, as well as allowing for the extending of user<br />
data. This is one of the areas of the book that is useful even to those<br />
that are not creating a broad CMS framework. User management and<br />
authentication are an aspect of most every system now. There are<br />
several ideas that I gleaned from this chapter. One of the ideas that I<br />
had not really put any consideration towards was initially brought up<br />
in chapter one and expounded on in this chapter. The idea was<br />
separating administrator login from regular user login. The purpose<br />
given was to allow for more restrictive measures to be put into place<br />
to give a greater level of security to critical settings. I knew this<br />
was a common aspect of many, many systems but until this point I had<br />
never seen a clear, precise reason for doing so. I also appreciate the<br />
fact that he pointed out table indexing as something that is to be<br />
considered early in the design process. Indexing is something that<br />
often gets overlooked in these kinds of books and as someone who is<br />
routinely addressing database performance in his every day job I love<br />
to database performance getting emphasis.</p>
<p>The placement of the<br />
chapter three is somewhat of an enigma to me. Chapter three details<br />
Brampton&#8217;s ideas for code organization. This is such a foundational<br />
concept of any system. It makes much more sense to me to have this<br />
content as chapter two. Nothing in this chapter is very dependent on<br />
what anything in the previous chapter. I like how he advocated the use<br />
of an auto loader to bring code in the system. He made his arguments<br />
with three very good points: code is loaded in the fewest places<br />
possible, knowledge of whether or not code is already loaded is<br />
irrelevant, and only the code that is used is loaded. I do not fully<br />
agree with how he created his auto loader. I prefer to use pear<br />
standards with file names to allow fully implicit mapping of requested<br />
classes to files. He also gives further credence to the singleton<br />
pattern which again, I am not a personal fan of. I can detail the<br />
reasons in a later post.</p>
<p>After the brief segue into code<br />
organization we get back to users and sessions in chapter four. In this<br />
chapter Brampton discusses why sessions are important and various<br />
security pitfalls related to sessions to avoid. In some senses this is<br />
a fairly basic chapter as sessions are a concept that is not at all<br />
specific to CMS frameworks and as result there is allot of information<br />
that many of you may already know. However, the fact that such<br />
attention is given to sessions again adds value outside of the pure CMS<br />
realm to this book. One topic that it brought up that I have seen<br />
neglected in other books is search engine bots. The concern that is<br />
raised is performance related as bots could cause potentially hundreds<br />
of new sessions to be started which could be taxing on your session<br />
store. This is not something I have ran into myself as my work is<br />
mostly on closed systems. So it was a somewhat interesting piece of<br />
advice.</p>
<p>In chapter five Brampton discusses interaction with the<br />
database. The first portion of the chapter talks about the benefits of<br />
relational databases, touches on caching, persistent connections,<br />
prepared statements, and several other basic considerations you must<br />
make when working with a database. The concept of abstracting the<br />
database is discussed as is data objects, security, and error handling.<br />
One thing I don&#8217;t really care for in this chapter is that he seems to<br />
shun prepared statements as something that is only useful if you are<br />
going to run the same query multiple times with the reasoning that they<br />
are more laborious to implement. I am not sure why he feels that they<br />
are laborious but to each their own I suppose. He did counter this<br />
however by providing some alternatives to the security benefits of<br />
prepared statements including escaping characters past to the often<br />
overlooked LIKE function in SQL to prevent wild card searches happening<br />
that are not intended.</p>
<p>Chapter six moves on from discussing<br />
database to talking about access control. A very good overview of how<br />
to implement a role-based access control system is given. In a fashion<br />
similar to chapter two Brampton outlines how he has implemented access<br />
control using code and database schema examples. A large emphasis is<br />
placed on caching which in my opinion is a critical part of access<br />
control as it is one of the most used components in any given CMS<br />
framework.</p>
<p>In chapter seven Brampton begins to discuss how to<br />
handle extensions. The opening sentence in this chapter is, &quot;Now we<br />
have reached a critical point in our book.&quot; I agree, extensibility is<br />
generally what will separate a good CMS from a great CMS. There are<br />
three different types of extension discussed: templates, modules, and<br />
components. There is a wealth of information, ideas, and concepts in<br />
this chapter. In the solution portion of this chapter he details how he<br />
has built his extension framework by taking advantage of the object<br />
oriented capabilities of PHP 5. While I think he does a good job laying<br />
down a basic foundation of concepts I wish he made use of actual<br />
interfaces for components and modules. Overall this is one of the<br />
chapters where you are almost certain to develop some ideas of how his<br />
work can translate into your software.</p>
<p>Of all the chapters in<br />
the book chapter 8 is the one that I feel could be more in depth.<br />
Caching in my opinion is a very important part of a CMS as it is going<br />
to be one of the first and easiest ways to increase performance. There<br />
was not allot of talk about centralized caching via a system like<br />
memcache and there was nothing mentioned of prefetching as an<br />
alternative to caching. He did detail some good reasoning about why you<br />
want to cache your XHTML (not everything has to be 100% dynamic) and he<br />
also briefly touched on centralized caching, I just don&#8217;t think it was<br />
given enough attention.</p>
<p>Chapter nine deals with menus. Like the<br />
other feature specific chapters it includes schema and code samples.<br />
Menus are a concept that is in my opinion hard to discuss in a such a<br />
way that you can describe a generalized implementation. If you are<br />
looking for help with ways to deal with menus and you don&#8217;t<br />
particularly care for how Brampton works with them then I would<br />
encourage you to at least try to look at his recommendations from a<br />
philosophical standpoint as once again I think he does give reasons for<br />
why he does things in certain ways.</p>
<p>Chapter ten was a very<br />
interesting chapter to read. In this chapter Brampton discusses<br />
internationalization. In both my career and personal life,<br />
internationalization is not something I have really needed to work<br />
with. That being said, one of my first open source projects was<br />
enabling internationalization in <a href="http://www.zentrack.net/">Zen Track</a>. It was very enlightening<br />
to read through this chapter and then look back at at how I did things.<br />
Had I read through this chapter and seen the discussion about gettext I<br />
would have been much better off. Internationalization is one of those<br />
concepts that seems to be harder to describe than it is to show code so<br />
the examples in this section wind up being incredibly simple.</p>
<p>Chapter<br />
eleven gives a very good overview of some of the different approaches<br />
you can take towards display. I think Brampton does an outstanding job<br />
of reassuring readers that you cannot create a solid argument for any<br />
one of the various display methods being better in every situation for<br />
every group of developer. Each has strengths and weaknesses that must<br />
be considered with the needs of the system developers and users kept in<br />
mind. He also brings up some outstanding points about WYSIWYG editors<br />
in CMSes and ways to cope with some of the problems that they introduce.</p>
<p>Chapter<br />
twelve is titled &#8216;Other Services&#8217; and really winds up being that<br />
&#8216;miscellaneous&#8217; for several common aspects of CMS frameworks that are<br />
important but not hard to discuss. Among some of the concepts discussed<br />
are XML parsing, configuration, more WYSIWYG editing, file and<br />
directory handling, and email. Code examples are given for each of<br />
these &#8216;services&#8217;</p>
<p>Chapter thirteen covers error handling. This is<br />
a fairly straight forward concept and this chapter does a good job at<br />
briefly covering different types of errors and gives you viable<br />
strategies for handling them. Due to the simplicity of the subject the<br />
chapter is incredibly short.</p>
<p>The final chapter of the book<br />
focuses on how to manage the various types of content one would want to<br />
store in a CMS. Several different content types are discussed. Ideas<br />
for content organization, tagging, handling comments, and even dealing<br />
with media is covered here.</p>
<p>Overall, I found this book to be<br />
much more interesting then I would have imagined from the title. I am<br />
not someone that routinely deals with CMS frameworks and I really don&#8217;t<br />
have any desire to write my own but I was still able to find a wealth<br />
of information and ideas that I can easily apply to the software that I<br />
do write. It is not really an exhaustive reference or review for any<br />
single aspect of CMS development but it gives you a fantastic overview<br />
of many different areas and can be used as a springboard to launch you<br />
into the areas that you find most interesting.</p>
<p>I do think there<br />
could be some improvement in the layout and structure of the book. It<br />
would have felt more natural if the generic concepts such as code<br />
organization, databases, and caching were handled first and then<br />
specific features were looked at. There were also a few off-the-cuff<br />
remarks and descriptions that are not entirely accurate. If you<br />
overlook those and focus on the meat of the book though I think it is a<br />
useful book.</p>

]]></content:encoded>
			<wfw:commentRss>http://digitalsandwich.com/archives/76-book-review-php5-cms-framework-development-by-martin-brampton.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Programming to Interfaces &gt; Programming to Implementations</title>
		<link>http://digitalsandwich.com/archives/75-programming-to-interfaces-programming-to-implementations.html</link>
		<comments>http://digitalsandwich.com/archives/75-programming-to-interfaces-programming-to-implementations.html#comments</comments>
		<pubDate>Wed, 15 Oct 2008 13:55:15 +0000</pubDate>
		<dc:creator>Mike Lively</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://digitalsandwich.com/?p=75</guid>
		<description><![CDATA[Over the last couple of months there is a concept in object-oriented programming that has been bothering me. This is the notion of &#8216;programming to an interface, not an implementation&#8217;. This is a principle I first learned about when reading &#8230; <a href="http://digitalsandwich.com/archives/75-programming-to-interfaces-programming-to-implementations.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[
<p>Over the last couple of months there is a concept in object-oriented programming that has been bothering me. This is the notion of &#8216;programming to an interface, not an implementation&#8217;. This is a principle I first learned about when reading <a href="http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612">&#8220;Design Patterns: Elements of Reusable Object-Oriented Software&#8221;</a> and then further solidified when I read <a href="http://www.amazon.com/Head-First-Design-Patterns/dp/0596007124">&#8220;Head First Design Patterns&#8221;</a>. So when I say &#8220;programming to an interface, not an implementation&#8221; what exactly do I mean? <a href="http://www.artima.com/weblogs/index.jsp?blogger=bv">Bill Venners</a> interviewed <a href="http://en.wikipedia.org/wiki/Erich_Gamma">Erich Gamma</a> (<a href="http://www.artima.com/lejava/articles/designprinciplesP.html">interview here</a>), one of the &#8220;Gang of Four&#8221; that co-authored &#8220;Design Patterns&#8221;, for <a href="http://www.artima.com/index.jsp">Artima Developer</a> during which time he asked the same question. The paraphrased answer is that it helps to limit the introduction of dependencies in your code. Limiting dependencies makes your code easier to test, easier to deploy and easier to change.</p>
<h3>What is the problem?</h3>
<p>You may now asking, &#8220;Mike, why does this bother you? It seems like a straightforward concept and I can&#8217;t imagine that you would disagree with it.&#8221; Well, you are mostly correct. I don&#8217;t at all disagree with this principle of reusable object-oriented design. In fact I try to embrace it. The reason it is bothering me is because I don&#8217;t believe it is really that simple of a concept and it is &#8216;accidentally&#8217; ignored by developers quite often.</p>
<h3>Story Time</h3>
<p>So, lets go back a couple of months. As some of you know (and most of you don&#8217;t) I am currently a lead developer for a loan management platform for <a href="http://www.sellingsource.com">Selling Source, Inc</a>. Part of my job as a lead developer is to oversee the architecture of our software and make sure it is going in the right direction. One of our projects at the moment is to revamp the search functionality of the software. I&#8217;ll try not to bore you with too many details (if you want more maybe I&#8217;ll write TWO blog posts this quarter.) We are denormalizing some of the frequently updated (and obnoxiously wide) tables involved in searching in order to allow moving indexes off of the primary tables in order to improve the update and insert speeds on the primary tables while improving the search speed in the new tables. While doing this we also decided it would be a good time to cleanup some of the code related to searching. One of the ideas was instead of building queries with string concatenations as weare currently doing we could utilize a &#8216;query builder&#8217; to create the query. This would allow for more extensibility as responsibility for building the query would reside in an object that could be modified and manipulated much more elegantly than a string.</p>
<p>In the interest of not reinventing the wheel I had one of my developers research other, already existing query builders. The results of his search pointed us to the Zend Framework query builder: <a href="http://framework.zend.com/apidoc/core/Zend_Db/Select/Zend_Db_Select.html">Zend_DB_Select</a>. Now I did have a few requirements in my head for what I would like to see out of this external query builder. This first one being that I wanted it to be stand alone. I did not want to have to bring in a bunch of extra baggage that I simply did not need. I was not looking for a framework, we already have one of those. I was looking for a component that we could plug into our existing framework.</p>
<p>Therein lied the problem with Zend_DB_Select. If you look at Zend_DB_Select from the view point of &#8220;What are its dependencies?&#8221; You will quickly find that there is a class wide dependency on <a href="http://framework.zend.com/apidoc/core/Zend_Db/Adapter/Zend_Db_Adapter_Abstract.html">Zend_Db_Adapter_Abstract</a>. This is an abstract class that essentially acts as a wrapper for the existing PHP database libraries. It provides a wealth of functionality including a unified interface for database interaction, a hook for a query profiler and some utility functions. I am sure in the grand scheme of the Zend Framework this is a very good and worth while class. However I would to make the argument that there is no reason for Zend_DB_Select to have a dependency on this class and the basis for that argument is an aspect of limiting your dependencies by truly programming to an interface.</p>
<h3>How We Can Use It</h3>
<p>So there are four ways that I would be able to use Zend_Db_Select as it is implemented right now.</p>
<ol>
<li>Change my code to utilize Zend&#8217;s db adapter for all of its connection needs. While the Zend adapter may well be better than the one I am using, I already have established use in over 100,000 lines of code of our own database connection classes. I just need to redesign our search code. Replacing all uses would be completely outside of the scope which in the business world is a bad place to be.</li>
<li>Create a Zend_DB_Adapter instance whenever you want to use the query builder. This is not a very good option either. We are using InnoDB for our database. InnoDB performance suffers pretty much linearly with the number of open connections. Creating two connections to the same database on most every request is just a bad idea.</li>
<li>Create an extension of Zend_DB_Adapter that decorates (wraps) an existing instance of my connection object. Of all three options so far this one is the most appealing. That being said I still do not think it is ideal. The database connection libraries we use at my office is much more encapsulated than the Zend counterpart. There is alot that Zend_DB_Adapter does that is not in our connection class, it is spread out to other classes such that it can be loaded on an as needed basis. This would make it take some time to write an adapter and would still necessitate us bringing Zend_DB_Adapter into our code base for basically a single purpose.</li>
<li>Modify Zend_Db_Select to remove the dependency on Zend_Db_Adapter_Abstract. This is actually the path we are currently exploring. The large downside to this is that we won&#8217;t be able to quickly get the upgrades or bug fixes from Zend Framework. However I am not too concerned. What we need this class to do is significantly more limited than its current feature set so we will be able to shrink it significantly and with less code comes more stability or at the very least fewer things that could break.</li>
</ol>
<p>We have identified that this dependency on Zend_Db_Adapter_Abstract is going to cause us all sorts of greif. Lets look at WHY Zend_DB_Select is dependent on Zend_Db_Adapter_Abstract. First, Zend_DB_Select is given the Zend_Db_Adapter_Abstract instance in the constructor. It is then set to the protected member variable $_adapter. So, lets see what all in $_adapter is called throughout the class:</p>
<ul>
<li><b>quoteInto():</b> 3</li>
<li><b>quoteIdentifier():</b> 6</li>
<li><b>quoteTableAs():</b> 1</li>
<li><b>quoteColumnAs():</b> 3</li>
<li><b>limit():</b> 1</li>
<li><b>query():</b> 1</li>
<li><b>getFetchMode():</b> 1</li>
</ul>
<p>The first thing you will notice is that all but 3 calls are to methods that are responsible for quoting an object. Now, indulge me for a moment and imagine that those were the only calls made. Why should I need a full fledged connection adapter object to perform quoting? I do realize that some quoting operations depend on the connection (character set, rdbms differences, etc.) But this should not mean that I <b>have</b> to use (in some form or another) Zend&#8217;s database adapters. I don&#8217;t want to use it. Mine works extremely well for what I want to do and I am already using it throughout my application.</p>
<h3>Moving Closer to Integration Utopia</h3>
<p>Now, in a dream world Zend_Db_Select would already be in a state that we could easily plug it into our code without having to go with one of the above four options. What if we created an interface that had a public method for each of the Zend_DB_Adapter_Abstract quote methods? It would look something like this:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;?php<br />
<br />
interface Zend_DB_IQuoter<br />
{<br />
&nbsp; &nbsp; public function quote($value, $type = null);<br />
&nbsp; &nbsp; public function quoteInto($text, $value, $type = null, $count = null);<br />
&nbsp; &nbsp; public function quoteIdentifier($ident, $auto=false);<br />
&nbsp; &nbsp; public function quoteColumnAs($ident, $alias, $auto=false);<br />
&nbsp; &nbsp; public function quoteTableAs($ident, $alias = null, $auto=false);<br />
}<br />
<br />
?&gt;</div></div>
<p>The Zend_DB_Adapter could easily be made to implement this interface (you would just have to add the interface to the class definition.) Then I could change the type hint in Zend_Db_Select&#8217;s constructor to use the new interface. So how would this help my cause? Well now I have a new option. This new option would be to create an implementation of this interface that worked with my existing connection objects. This would be significantly easier than alternative 3. The interface would be well defined and significantly smaller than the Zend_Db_Adapter_Abstract class.</p>
<p>From a design standpoint this interface makes more sense too. The only thing we care about is quoting. So why not specify (via the constructor type hint) that this is really the only thing we are concerned with. It would make the true dependencies of our class much more transparent. From an extensibility and flexibility stand point this is very useful.</p>
<p>So, we still have those other pesky three calls to the Zend_Db_Adapter_Abstract class.</p>
<ul>
<li><b>limit():</b> 1</li>
<li><b>query():</b> 1</li>
<li><b>getFetchMode():</b> 1</li>
</ul>
<p>Lets explore why these are there.</p>
<p>The reason why limit() is being used is because different database platforms have different ways to specify limits and offsets. For MySQL you can use LIMIT <N>, LIMIT <N>, <N> or LIMIT <N> OFFSET <N>. Oracle from what I understand doesn&#8217;t implement limits at all. Now one thing that I find uniquely curious is that all of a sudden in Zend they have moved query building back into their adapters in a very explicit way. So what would I do? Well, since we have already established that quoting really should be connection specific and we have no identified that limits are really connection specific (by virtue of being RDBMS specific) then we could make a small change to the interface above. The first would be to add the limit() function. The next would be to change the name. It is no longer a &#8216;Quoter&#8217; it is now essentially performing all connection specific alterations for our queries. So lets try out the name Zend_Db_IQueryModifier. Now before you go yelling at me for that name, let me first say that I suck at class naming. You are more than welcome to &#8216;insert your name here&#8217;.</p>
<p>This leaves us with a finding home for query and getFetchMode(). I have a problem with these two method calls. They are both used on a method called query() in the Zend_Db_Select. For the kind of object I am looking for, I don&#8217;t think these should be here. We already have a class that is responsible for executing queries. Instead of calling &#8216;query()&#8217; on my query builder object I would much rather pass that object to my adapter. Which is actually what the Zend Framework implementation of this method does. If you do not want to make your adapter dependent on the query object (which I personally would not want to do either) you could have the Zend_Db_Select have a method to return the query. (Zend_Db_Select implements __toString()).</p>
<p>With these changes I (or anyone for the matter) could use the Zend_Db_Select class completely stand alone with no need for any additional, non-exception Zend classes.</p>
<h3>I am a Lover, Not a Hater (Oh and I&#8217;m Stupid Too)</h3>
<p>It is not my purpose to pick on Zend Framework. I am confident that they are not the only example of not clearly thinking through dependencies and I am equally confident that many people find Zend Framework to be very useful for their needs. They just happened to have an easy real world example of ways that code can be made better and I happened to have to spend a significant amount of time inspecting the code for reasons other than writing an article. Just to prove I am not trying to point the finger I have an example that is arguably worse than the one above and it is in code that I wrote. A <a href="http://www.phpunit.de/ticket/554">bug was recently opened for PHPUnit</a> that essentially asked me why I had type hints for the default database connection class of the database extension in several of my files. There was no real need for this. I wasn&#8217;t as interested in a wrapped version of the class as I was in simply retrieving meta data. In fact to make things even worse I ALREADY HAD an interface for this data. I just simply did not use it in this case. It was a terrible oversight of mine and is an example of even when you know better these kind of dependencies can slip by. If you would like more details I can outline them in another post.</p>
<h3>I am Almost Done</h3>
<p>So, at the expense of ending this ridiculously long blog posting lets go back to the Erich Gamma interview. In the spirit of programming to interfaces, not implementations, I believe you should limit dependencies to responsibilities not complete classes. If a class truly has only one responsibility, then it is probably okay to use that class name as the type hint. If a class has multiple responsibilities and you have deemed it necessary than I would strongly recommend you create interfaces to indicate the public methods for those responsibilities and use those in your type hints as appropriate.</p>
<p>Now, if you read through the entire interview (and I suggest you do) you will notice that Erich makes some points that might on the surface seem to contradict what I am saying. Erich states &#8220;An abstract class is good as well. In fact, an abstract class gives you more flexibility when it comes to evolution. You can add new behavior without breaking clients.&#8221; This is a very valid point. He does however go on to state, &#8220;As always there is a trade-off, an interface gives you freedom with regard to the base class, an abstract class gives you the freedom to add new methods later.&#8221; So you do have a decision to make. My issue with Zend_Db_Select turned out to be that the dependency in code was deeper than it needed to be. Sometimes you will have a dependency on an abstract class that will be perfectly fine. So long as you keep responsibilities to a minimum via composition among other means (which the second point in that interview helps with.) Then you should find it very easy to program to interfaces.</p>

]]></content:encoded>
			<wfw:commentRss>http://digitalsandwich.com/archives/75-programming-to-interfaces-programming-to-implementations.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>2008 DC PHP Conference &#8211; Advanced PHPUnit Testing</title>
		<link>http://digitalsandwich.com/archives/74-2008-dc-php-conference-advanced-phpunit-testing.html</link>
		<comments>http://digitalsandwich.com/archives/74-2008-dc-php-conference-advanced-phpunit-testing.html#comments</comments>
		<pubDate>Wed, 04 Jun 2008 13:55:41 +0000</pubDate>
		<dc:creator>Mike Lively</dc:creator>
				<category><![CDATA[PHP Testing]]></category>

		<guid isPermaLink="false">http://digitalsandwich.com/?p=74</guid>
		<description><![CDATA[And here are the advanced PHPUnit slides! &#124; View &#124; Upload your own]]></description>
				<content:encoded><![CDATA[
<p>And here are the advanced PHPUnit slides!</p>
<div id="__ss_446619" style="width: 425px; text-align: left;"><object width="425" height="355" style="margin: 0px;"><param value="http://static.slideshare.net/swf/ssplayer2.swf?doc=advanced-php-unit-testing2-1212587249704441-9" name="movie" /><param value="true" name="allowFullScreen" /><param value="always" name="allowScriptAccess" /><embed width="425" height="355" allowfullscreen="true" allowscriptaccess="always" type="application/x-shockwave-flash" src="http://static.slideshare.net/swf/ssplayer2.swf?doc=advanced-php-unit-testing2-1212587249704441-9" /></object>
<div style="font-size: 11px; font-family: tahoma,arial; height: 26px; padding-top: 2px;"><a href="http://www.slideshare.net/?src=embed"><img alt="SlideShare" style="border: 0px none ; margin-bottom: -5px;" src="http://static.slideshare.net/swf/logo_embd.png" /></a> | <a title="View Advanced PHPUnit Testing on SlideShare" href="http://www.slideshare.net/mjlivelyjr/advanced-phpunit-testing?src=embed">View</a> | <a href="http://www.slideshare.net/upload?src=embed">Upload your own</a></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://digitalsandwich.com/archives/74-2008-dc-php-conference-advanced-phpunit-testing.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>2008 DC PHP Conference &#8211; Automated Unit Testing</title>
		<link>http://digitalsandwich.com/archives/73-2008-dc-php-conference-automated-unit-testing.html</link>
		<comments>http://digitalsandwich.com/archives/73-2008-dc-php-conference-automated-unit-testing.html#comments</comments>
		<pubDate>Wed, 04 Jun 2008 13:52:32 +0000</pubDate>
		<dc:creator>Mike Lively</dc:creator>
				<category><![CDATA[PHP Testing]]></category>

		<guid isPermaLink="false">http://digitalsandwich.com/?p=73</guid>
		<description><![CDATA[As promised here are my automated unit testing slides for the 2008 DC PHP conference. &#124; View &#124; Upload your own]]></description>
				<content:encoded><![CDATA[
<p>As promised here are my automated unit testing slides for the 2008 DC PHP conference.</p>
<div style="width:425px;text-align:left" id="__ss_446614"><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=automated-unit-testing-1212587126813053-9"/><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=automated-unit-testing-1212587126813053-9" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"><a href="http://www.slideshare.net/?src=embed"><img src="http://static.slideshare.net/swf/logo_embd.png" style="border:0px none;margin-bottom:-5px" alt="SlideShare"/></a> | <a href="http://www.slideshare.net/mjlivelyjr/automated-unit-testing?src=embed" title="View Automated Unit Testing on SlideShare">View</a> | <a href="http://www.slideshare.net/upload?src=embed">Upload your own</a></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://digitalsandwich.com/archives/73-2008-dc-php-conference-automated-unit-testing.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
