<?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>Jeff Carouth&#039;s blog&#187; Unit Testing</title>
	<atom:link href="http://carouth.com/tag/unit-testing/feed/" rel="self" type="application/rss+xml" />
	<link>http://carouth.com</link>
	<description>Ramblings of a Web Application Developer</description>
	<lastBuildDate>Sat, 06 Feb 2010 21:36:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Stubbing an Interface</title>
		<link>http://carouth.com/2009/11/18/stubbing-an-interface/</link>
		<comments>http://carouth.com/2009/11/18/stubbing-an-interface/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 17:41:33 +0000</pubDate>
		<dc:creator>jcarouth</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Data Sources]]></category>
		<category><![CDATA[Interfaces]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://carouth.com/?p=141</guid>
		<description><![CDATA[One of the topics I talk about frequently is coding to an interface. There is an abundance of evidence why one might choose to do so but today I'd like to talk about one benefit in terms of unit testing—another topic I love to talk about. To illustrate the benefit I will use an example [...]]]></description>
			<content:encoded><![CDATA[<p>One of the topics I talk about frequently is coding to an interface. There is an abundance of evidence why one might choose to do so but today I'd like to talk about one benefit in terms of unit testing—another topic I love to talk about. To illustrate the benefit I will use an example of having the data source coded against the interface thereby allowing the consumer of the data source to ignore the specifics behind how data is stored, e.g., in a relational database or in a key-value store, and concentrate solely on requesting the appropriate data. Before I get to the code, however, I think it's important that I define some of the scope of this post.</p>
<h2>Goals of a Unit Test Suite</h2>
<p>Other than exercising a substantial portion of your code a unit test suite must be capable of running quickly lest it be a burden on development. Having a burdensome, slow-running test suite will only encourage developers to ignore it and only run it when absolutely necessary. This, in turn, will make maintenance of the test suite more difficult and probably result in fragile or poor tests which ultimately will leave a bad taste in the developer's mouth about unit testing, and we wouldn't want that, now would we?</p>
<p>One sure-fire way to decrease the speed of a test suite is to make it rely on real-world data sources such as your relational database or even a web service. Imagine a test suite for an application that relies on Twitter's availability. I can assure you that I would not want to run that test suite. The fail whale is annoying enough on the web. But I digress. Being able to emulate a data storage source is paramount to the speed of a unit test. Stubbing is one technique employed to do such a thing.</p>
<h2>A Data Source Interface</h2>
<p>A basic data source needs the implement the standard <abbr title="Create, read, update, and delete">CRUD</abbr> methods and can be defined as follows:</p>
<pre class="brush: php;">interface ICrudDataSource
{
    public function create(array $data);

    public function read($id);

    public function update($id, array $data);

    public function delete($id);
}
</pre>
<p>If this were a real interface there would be PHPDoc blocks to indicate the behavior of the methods and parameter types, but for the sake of the example I omit them. Now we can implement this interface in our database table class and define the behavior for each of the methods in terms of how our chosen rdbms will understand them, e.g., create() is an INSERT statement, read() is a SELECT statement, so on and so forth.</p>
<p>We can then use this class in our unit tests and it will actually test that the database vendor correctly implemented the INSERT, SELECT, UPDATE, and DELETE statements and that we are calling them appropriately. While I do think the latter should be tested when we look at the database abstraction implementation, the former is not necessary and will only slow down tests that <em>use</em> the data source code but <em>don't directly depend on it</em> being a database, for example. In such a case a simple array-based storage mechanism will work.</p>
<h2>Array-based Stub for Unit Testing</h2>
<p>Thus, we implement the ICrudDataSource interface in a stub that is used for our unit tests that need to interact with the data storage but necessarily need to interact with the specific data storage used in production.</p>
<pre class="brush: php;">class UserDataStorageStub implements ICrudDataSource
{
    protected $_store;

    public function __construct()
    {
        $this-&gt;_store = array();
    }

    public function create(array $data)
    {
        if (!$this-&gt;exists($data['id'])) {
            $this-&gt;_store[$data['id']] = $data;
            return true;
        }

        return false;
    }

    public function read($id)
    {
        if ($this-&gt;exists($id)) {
            return $this-&gt;_store[$id];
        }

        return false;
    }

    public function update($id, array $data)
    {
        if (!$this-&gt;exists($id)) {
            return false;
        }

        $this-&gt;_store[$id] = $data;
    }

    public function delete($id)
    {
        unset($this-&gt;_store[$id]);
    }

    private function exists($id)
    {
        return array_key_exists($id, $this-&gt;_store);
    }
}</pre>
<p>With this array-based implementation the unit tests will be fast regardless of the availability of the actual data source or the load on that data source. This stub, or a stub that extends this one, can also be easily pre-populated with test data to allow for testing with fixed data (although this can lead to very brittle tests if done lackadaisically).</p>
<div class="acc_license"><a href="http://creativecommons.org/licenses/by/3.0/"><img src="http://i.creativecommons.org/l/by/3.0/88x31.png" alt="by" /></a></div><!--<rdf:RDF xmlns="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="http://creativecommons.org/licenses/by/3.0/" /></Work><License rdf:about="http://creativecommons.org/licenses/by/3.0/"><requires rdf:resource="http://creativecommons.org/ns#Attribution" /><permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><permits rdf:resource="http://creativecommons.org/ns#Distribution" /><permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><requires rdf:resource="http://creativecommons.org/ns#Notice" /></License></rdf:RDF>-->


Share:


	<a rel="nofollow"  target="_blank" href="http://www.printfriendly.com/print?url=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F18%2Fstubbing-an-interface%2F&amp;partner=sociable" title="Print"><img src="http://carouth.com/wp-content/plugins/sociable/images/printfriendly.png" title="Print" alt="Print" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F18%2Fstubbing-an-interface%2F&amp;title=Stubbing%20an%20Interface&amp;bodytext=One%20of%20the%20topics%20I%20talk%20about%20frequently%20is%20coding%20to%20an%20interface.%20There%20is%20an%20abundance%20of%20evidence%20why%20one%20might%20choose%20to%20do%20so%20but%20today%20I%27d%20like%20to%20talk%20about%20one%20benefit%20in%20terms%20of%20unit%20testing%E2%80%94another%20topic%20I%20love%20to%20talk%20about.%20To%20illust" title="Digg"><img src="http://carouth.com/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F18%2Fstubbing-an-interface%2F&amp;title=Stubbing%20an%20Interface&amp;notes=One%20of%20the%20topics%20I%20talk%20about%20frequently%20is%20coding%20to%20an%20interface.%20There%20is%20an%20abundance%20of%20evidence%20why%20one%20might%20choose%20to%20do%20so%20but%20today%20I%27d%20like%20to%20talk%20about%20one%20benefit%20in%20terms%20of%20unit%20testing%E2%80%94another%20topic%20I%20love%20to%20talk%20about.%20To%20illust" title="del.icio.us"><img src="http://carouth.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F18%2Fstubbing-an-interface%2F&amp;t=Stubbing%20an%20Interface" title="Facebook"><img src="http://carouth.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.google.com/bookmarks/mark?op=edit&amp;bkmk=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F18%2Fstubbing-an-interface%2F&amp;title=Stubbing%20an%20Interface&amp;annotation=One%20of%20the%20topics%20I%20talk%20about%20frequently%20is%20coding%20to%20an%20interface.%20There%20is%20an%20abundance%20of%20evidence%20why%20one%20might%20choose%20to%20do%20so%20but%20today%20I%27d%20like%20to%20talk%20about%20one%20benefit%20in%20terms%20of%20unit%20testing%E2%80%94another%20topic%20I%20love%20to%20talk%20about.%20To%20illust" title="Google Bookmarks"><img src="http://carouth.com/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F18%2Fstubbing-an-interface%2F&amp;title=Stubbing%20an%20Interface" title="Reddit"><img src="http://carouth.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F18%2Fstubbing-an-interface%2F&amp;title=Stubbing%20an%20Interface" title="StumbleUpon"><img src="http://carouth.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=Stubbing%20an%20Interface%20-%20http%3A%2F%2Fcarouth.com%2F2009%2F11%2F18%2Fstubbing-an-interface%2F" title="Twitter"><img src="http://carouth.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://carouth.com/2009/11/18/stubbing-an-interface/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Maintainable Unit Tests with PHPUnit Revised</title>
		<link>http://carouth.com/2009/11/05/maintainable-unit-tests-with-phpunit-revised/</link>
		<comments>http://carouth.com/2009/11/05/maintainable-unit-tests-with-phpunit-revised/#comments</comments>
		<pubDate>Fri, 06 Nov 2009 00:50:16 +0000</pubDate>
		<dc:creator>jcarouth</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHPUnit]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://carouth.com/?p=134</guid>
		<description><![CDATA[One Step Back
In my previous post I chose an example that did not illustrate my point. In this post I will address the issues with previous post, specifically those brought to light by Matthew Weier O'Phinney in his comment.
His first point is that changing the method signature on a constructor should and will break any [...]]]></description>
			<content:encoded><![CDATA[<h1>One Step Back</h1>
<p>In my previous post I chose an example that did not illustrate my point. In this post I will address the issues with previous post, specifically those brought to light by <a href="http://weierophinney.net/matthew">Matthew Weier O'Phinney</a> in his <a href="http://carouth.com/2009/11/05/maintainable-unit-tests-with-phpunit/#comment-76">comment</a>.</p>
<p>His first point is that changing the method signature on a constructor should and will break any client code, thus modifications will be necessary to the tests. I agree with this wholeheartedly and my choice of using a constructor was obviously flawed. Let's just chalk this one up to not having had my coffee as I typed that post…</p>
<p>His second point deals with using the tools available to you within the framework. Specifically he mentions the use of the setUp() method which executes prior to each test case and is normally used to establish required state, set up fixtures, etc. I already committed to the constructor example so I carried it through this segment of the code. It was, again, a bad decision.</p>
<p>So this post will serve as a replacement for the old post to better illustrate my point.</p>
<h1>Maintainable Tests</h1>
<p>Great unit testing is a learned skill. Unfortunately the motivation developers have for dabbling in writing unit tests for an application usually comes from someone else, e.g., his or her boss, a fellow team member, etc. This leads to writing tests just to have tests which, in my opinion at least, is no better than not having tests in the first place.</p>
<p>A non-maintainable code base is know to be a problem. The corollary, a non-maintainable test suite is a huge problem, is also true. If you cannot maintain your test suite, what is the point? Any time a unit test reaches beyond a single or violates the <abbr title="Don't Repeat Yourself">DRY</abbr> principle a development team could find that the test suite is verging on a non-maintainable state.</p>
<h2>Testing Units More Than Once</h2>
<p>If a requirement or business rule is tested more than once in the test suite, as is the case in the following example, any changes become difficult to manage. In this example the business requirement that changed is that all cars start with five gallons of gas before they arrive at your showroom. Thus a brand new car, i.e., the default constructed car, will not have an empty gas tank and should be able to start—unless something else is wrong, but I am a programmer not a mechanic.</p>
<pre class="brush: php;">class CarTest extends PHPUnit_Framework_TestCase
{
    protected $_car;

    public function setUp()
    {
        $this-&gt;_car = new Car();
    }

    public function testGasolinePresentBeforeStarting()
    {
        $this-&gt;setExpectedException('GasTankEmptyException');
        $this-&gt;_car-&gt;start();
    }

    public function testCarStartsAfterFillup()
    {
        $fuelVessel = $this-&gt;getMock(
            'GasolineContainer',
            array('dispense')
        );
        //set expectation on fuelContainer to give 10
        //gallons of fuel when dispense is called

        try {
            $this-&gt;_car-&gt;start();
            $this-&gt;fail(
                'Empty gas tank but no exception caught'
            );
        } catch(GasTankEmptyException $e) {
            $this-&gt;_car-&gt;addGasoline($fuelVessel);
        }

        $this-&gt;_car-&gt;start();
        $this-&gt;assertTrue($this-&gt;_car-&gt;isRunning());
    }
}</pre>
<p>This change is not necessarily a regression because code that used the Car object before should still work as intended the cars will just start from scratch with some gasoline. Since we changed this requirement both tests in the above code will fail. The first will fail because we assumed a brand new car object would have no gasoline in the tank. The same for the second test. The code repeats itself, and so does my explanation.</p>
<p>Avoiding the duplication in the second test by immediately filling up the car with gasoline solves the problem of having to dig through the unit test and makes the second test case a true unit test. As it stands above, it tests two units: 1) that a car with an empty tank throws a specific exception and 2) that after adding gasoline to the car it will start.</p>
<h2>Using the Tools Correctly</h2>
<p>I knew about setUp() and tearDown() but I was trying too hard to come up with a fancy solution to my problem. The problem, as it should have been explained previously, occurs when a test case has groups of tests that require different configurations of the UUT. For example, sticking with our Car class, we have several tests that require a stock instance of Car while a group of others needs a car with a special engine. We can accomplish this as follows:</p>
<pre class="brush: php;">class CarTest extends PHPUnit_Framework_TestCase
{
    protected $_car;

    public function setUp()
    {
        $this-&gt;_car = new Car();
    }

    public function testSomethingWithAStockCar()
    {
        //work
        $this-&gt;assert(…);
    }

    public function testSomethingElseWithStockCar()
    {
        //same as above
    }

    public function testCarWithDifferentEngine()
    {
        //mock/stub of engine: $engine
        $this-&gt;_car-&gt;setEngine($engine);
    }

    public function testCarWithDifferentEngineAgain()
    {
        //mock/stub of engine: $engine
        $this-&gt;_car-&gt;setEngine($engine);
    }
}</pre>
<p>Assuming I abstract the creation of the mock engine into a helper method, I still have a lot of duplicated code and I still have to call the setEngine() method in each test. That's absurd. One solution is to create a new test case for the different configuration; I'll call it CarWithEngineBTest.</p>
<pre class="brush: php;">class CarWithEngineBTest extends PHPUnit_Framework_TestCase
{
    protected $_car;

    public function setUp()
    {
        $engine = $this-&gt;getMock('EngineB');
        //…configure mock object…
        $this-&gt;_car = new Car();
        $this-&gt;_car-&gt;setEngine($engine);
    }

    //test cases that need this configuration
}</pre>
<p>And remove these specific tests from the previous test case. This probably isn't the only way to solve this issue, but it does seem better than my previous factory method "solution".</p>
<p>The example still isn't perfect, but I couldn't come up with a better one. You are more than welcomed to weigh in.</p>
<div class="acc_license"><a href="http://creativecommons.org/licenses/by/3.0/"><img src="http://i.creativecommons.org/l/by/3.0/88x31.png" alt="by" /></a></div><!--<rdf:RDF xmlns="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="http://creativecommons.org/licenses/by/3.0/" /></Work><License rdf:about="http://creativecommons.org/licenses/by/3.0/"><requires rdf:resource="http://creativecommons.org/ns#Attribution" /><permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><permits rdf:resource="http://creativecommons.org/ns#Distribution" /><permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><requires rdf:resource="http://creativecommons.org/ns#Notice" /></License></rdf:RDF>-->


Share:


	<a rel="nofollow"  target="_blank" href="http://www.printfriendly.com/print?url=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F05%2Fmaintainable-unit-tests-with-phpunit-revised%2F&amp;partner=sociable" title="Print"><img src="http://carouth.com/wp-content/plugins/sociable/images/printfriendly.png" title="Print" alt="Print" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F05%2Fmaintainable-unit-tests-with-phpunit-revised%2F&amp;title=Maintainable%20Unit%20Tests%20with%20PHPUnit%20Revised&amp;bodytext=One%20Step%20Back%0D%0AIn%20my%20previous%20post%20I%20chose%20an%20example%20that%20did%20not%20illustrate%20my%20point.%20In%20this%20post%20I%20will%20address%20the%20issues%20with%20previous%20post%2C%20specifically%20those%20brought%20to%20light%20by%20Matthew%20Weier%20O%27Phinney%20in%20his%20comment.%0D%0A%0D%0AHis%20first%20point%20is%20th" title="Digg"><img src="http://carouth.com/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F05%2Fmaintainable-unit-tests-with-phpunit-revised%2F&amp;title=Maintainable%20Unit%20Tests%20with%20PHPUnit%20Revised&amp;notes=One%20Step%20Back%0D%0AIn%20my%20previous%20post%20I%20chose%20an%20example%20that%20did%20not%20illustrate%20my%20point.%20In%20this%20post%20I%20will%20address%20the%20issues%20with%20previous%20post%2C%20specifically%20those%20brought%20to%20light%20by%20Matthew%20Weier%20O%27Phinney%20in%20his%20comment.%0D%0A%0D%0AHis%20first%20point%20is%20th" title="del.icio.us"><img src="http://carouth.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F05%2Fmaintainable-unit-tests-with-phpunit-revised%2F&amp;t=Maintainable%20Unit%20Tests%20with%20PHPUnit%20Revised" title="Facebook"><img src="http://carouth.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.google.com/bookmarks/mark?op=edit&amp;bkmk=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F05%2Fmaintainable-unit-tests-with-phpunit-revised%2F&amp;title=Maintainable%20Unit%20Tests%20with%20PHPUnit%20Revised&amp;annotation=One%20Step%20Back%0D%0AIn%20my%20previous%20post%20I%20chose%20an%20example%20that%20did%20not%20illustrate%20my%20point.%20In%20this%20post%20I%20will%20address%20the%20issues%20with%20previous%20post%2C%20specifically%20those%20brought%20to%20light%20by%20Matthew%20Weier%20O%27Phinney%20in%20his%20comment.%0D%0A%0D%0AHis%20first%20point%20is%20th" title="Google Bookmarks"><img src="http://carouth.com/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F05%2Fmaintainable-unit-tests-with-phpunit-revised%2F&amp;title=Maintainable%20Unit%20Tests%20with%20PHPUnit%20Revised" title="Reddit"><img src="http://carouth.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fcarouth.com%2F2009%2F11%2F05%2Fmaintainable-unit-tests-with-phpunit-revised%2F&amp;title=Maintainable%20Unit%20Tests%20with%20PHPUnit%20Revised" title="StumbleUpon"><img src="http://carouth.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=Maintainable%20Unit%20Tests%20with%20PHPUnit%20Revised%20-%20http%3A%2F%2Fcarouth.com%2F2009%2F11%2F05%2Fmaintainable-unit-tests-with-phpunit-revised%2F" title="Twitter"><img src="http://carouth.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://carouth.com/2009/11/05/maintainable-unit-tests-with-phpunit-revised/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maintainable Unit Tests with PHPUnit</title>
		<link>http://carouth.com/2009/11/05/maintainable-unit-tests-with-phpunit/</link>
		<comments>http://carouth.com/2009/11/05/maintainable-unit-tests-with-phpunit/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 16:45:14 +0000</pubDate>
		<dc:creator>jcarouth</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Maintainable Code]]></category>
		<category><![CDATA[PHPUnit]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://carouth.com/?p=126</guid>
		<description><![CDATA[Better version of this post coming. Thanks to Matthew Weier O'Phinney's comment I see that this post did not convey the point in the manner I wanted, and I thought of a better solution to the problem. Thus I am closing comments on this post pending the new version. Read the modified version.
Great unit testing [...]]]></description>
			<content:encoded><![CDATA[<p><div class="note"><div class="noteimportant">Better version of this post coming. Thanks to <a href="http://weierophinney.net/matthew">Matthew Weier O'Phinney's</a> comment I see that this post did not convey the point in the manner I wanted, and I thought of a better solution to the problem. Thus I am closing comments on this post pending the new version. <a href="http://carouth.com/2009/11/05/maintainable-unit-tests-with-phpunit-revised/">Read the modified version</a>.</div></div></p>
<p>Great unit testing is a learned skill.  Unfortunately the motivation developers have for dabbling in writing unit tests for an application usually comes from someone else, e.g., his or her boss, a fellow team member, etc. This leads to <strong>writing tests just to have tests</strong> which, in my opinion at least, is no better than not having tests in the first place.</p>
<p>A non-maintainable code base is know to be a problem. The corollary, a non-maintainable test suite is a huge problem, is also true. If you cannot maintain your test suite, what is the point?</p>
<p>Looking at an example, I frequently see test cases that have the <abbr title="Unit Under Test">UUT</abbr>'s constructor called at the beginning of each test. This works fine up until the requirements change and the constructor now requires an instance of IDataSource or an array instead of a string. Now each test must be touched, i.e., development time devoted to each test function, to implement this change.</p>
<pre class="brush: php;">class CarTest extends PHPUnit_Framework_TestCase
{
    public function testStartFailsIfGasTankEmpty()
    {
        $car = new Car();
        $this-&gt;setExpectedException('GasTankEmptyException');
        $car-&gt;start();
    }

    public function testSomethingElse()
    {
        $car = new Car();
        //assert something
    }

    //so on and so forth
}</pre>
<p>Instead, if a developer uses a factory method within the test suite to return a default instance of the UUT, the change to the tests is only necessary in cases where the initialized state of the instance must change via the constructor, as follows.</p>
<pre class="brush: php;">class CarTest extends PHPUnit_Framework_TestCase
{
    public function testStartFailsIfGasTankEmpty()
    {
        $car = $this-&gt;Factory_Car();
        //…snip…
    }

    //…snip…

    private function Factory_Car()
    {
        return new Car();
    }
}</pre>
<p>Okay, that works for a while. But what if in ninety-five percent of the tests you need to use the "default constructor"—in quotes because PHP classes can only have one constructor—but the other five percent need to pass in some configuration options. You have two choices:</p>
<ol>
<li>create a new factory method for each group of, e.g., <em>Factory_Car</em> and <em>Factory_SuperFastCar</em>, or</li>
<li>allow the existing factory method to take arguments and pass them on to the constructor.</li>
</ol>
<p>Which you choose depends on the unique situation of your test case. For this example I'll assume there are ten tests. Seven of the tests use a default <em>Car</em> object while the other three each need a unique Car instance, thus each passes a configuration argument to the constructor. To handle this situation the factory method will make use of the PHP functions <em>func_get_args()</em> and <em>call_user_func_array()</em>.</p>
<pre class="brush: php;">public function Factory_Car()
{

    $car = new Car();
    if (func_num_args() &gt; 0) {
        $args = func_get_args();
        call_user_func_array(array($car, '__construct'), $args);
    }

    return $car;
}</pre>
<p>This factory method allows each test to retrieve a properly-configured instance—where configuration is done via the constructor—of the <em>Car</em> class with which to work without sacrificing maintainability. One caveat: the three test methods in the example will need to be modified if the constructor's signature changes, but, last time I checked, three is less than ten.</p>
<div class="acc_license"><a href="http://creativecommons.org/licenses/by/3.0/"><img src="http://i.creativecommons.org/l/by/3.0/88x31.png" alt="by" /></a></div><!--<rdf:RDF xmlns="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="http://creativecommons.org/licenses/by/3.0/" /></Work><License rdf:about="http://creativecommons.org/licenses/by/3.0/"><requires rdf:resource="http://creativecommons.org/ns#Attribution" /><permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><permits rdf:resource="http://creativecommons.org/ns#Distribution" /><permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><requires rdf:resource="http://creativecommons.org/ns#Notice" /></License></rdf:RDF>--><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://carouth.com/2009/11/05/maintainable-unit-tests-with-phpunit/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The Modern PHP Workflow</title>
		<link>http://carouth.com/2009/10/20/the-modern-php-workflow/</link>
		<comments>http://carouth.com/2009/10/20/the-modern-php-workflow/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 19:55:51 +0000</pubDate>
		<dc:creator>jcarouth</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Agile Development]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[php|architect]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://carouth.com/?p=99</guid>
		<description><![CDATA[This article was originally published in November 2008 by php&#124;architect.
Over time we have all seen projects that become great success stories and our fair share of projects that become epic failures. Some of this can be blamed on the idea behind the project but I challenge you to consider that part of failure can be [...]]]></description>
			<content:encoded><![CDATA[<p><div class="note"><div class="noteclassic">This article was originally published in November 2008 by <a href="http://www.phparch.com/magazine/index/86">php|architect</a>.</div></div></p>
<p>Over time we have all seen projects that become great success stories and our fair share of projects that become epic failures. Some of this can be blamed on the idea behind the project but I challenge you to consider that part of failure can be attributed to a lack of constant supervision of the project. This is not to say that any one person is in charge of ensuring a project is on target with the original goals, or even that a project manager is responsible for testing the project throughout development. Rather, I'd like you to consider the work flow used on those failed projects and compare it with a more modern approach to development. While this won't guarantee the success of every project, using proven tools and methods such as unit testing with PHPUnit, an automated build system such as Phing, and a continuous integration server such as Xinc will greatly improve the quality and timeliness of your future projects.</p>
<h1>Preparations</h1>
<p>In order to follow along with this article you will need to equip yourself with the proper tools. Luckily between pear and the pecl obtaining these tools is the matter of a few characters typed into the command line. Note that thorough installation instructions can be found on the websites for each of the tools which are http://www.phpunit.de for PHPUnit,  http://xinc.googlecode.com for Xinc, and http://phing.info for Phing.</p>
<h1>The Foundation: PHPUnit</h1>
<p>Personally before I began my journey into the world of “Agile” development practices, specifically unit testing, I was already familiar with the basic concepts behind why it is a good idea but I was a little intimidated by the seemingly steep learning curve. If you're anything like me you have thought about the amount of additional time your projects will take because of the added burden of writing tests, you think that testing is something reserved for the extra weeks you tacked on to the schedule for this project and comes in the flavor of “Try out this application and see if you can break it.” or worse yet you think that your code is so impressively impeccable that you could not possibly benefit from writing these silly little tests. I am here to tell you that I was wrong in all of those assumptions. It took a while for me to realize the benefit and I will not try to convince you that it took no time at all to adapt my thought process to testing, but I can tell you that as a result I am more confident in my code, my projects are easier to maintain, and my clients and employers are much more satisfied with my work.</p>
<p>The toughest part of getting started with unit testing is deciding where to being your journey of learning how to test your applications. To help you along we are going to work together to develop an application to track the whereabouts of various items needed for school as a collegiate student. For this purpose we are going to assume that our student needs to track his notebooks, his textbooks, his planner, and his laptop which can be in his desk or in his backpack. Over the course of this example I may introduce a few bugs--some purposely, some otherwise--if there is any doubt in your mind about the code, assume it is for example sake.</p>
<p>Coupled with unit testing the technique of test-driven development is thrown into the mix and we're going drive the development of our application with testing. The principle behind test-driven development (TDD) is that we first write tests that describe how our code functions, more specifically how it is used, and then we write the code that allows the tests to pass. This might seem counter-intuitive at first, but we write failing tests first then make the code conform to our tests thus making our tests the contract to which we design our code. Coding the opposite direction generally leads to bending test code to fit the workings of your code base which in turn will lead to massive refactoring and potential code hernias in the future. If you aren't familiar with the term “code hernia” it is essentially a fragment of code that is in place that may be difficult to understand, most likely causes awkward use of the code base or API, and is only explained by lengthy comment blocks. The maintenance nightmare associated with such awkward code is exactly the type of problem we hope to solve by unit testing our code.<br />
<span id="more-99"></span></p>
<p>We will start by looking at the various places an object (textbook, notebook, planner, or laptop) can be located. It should be obvious at this point that each of these locations is merely a container that can accept a student's belongings, thus we will work on creating the base container class that each location will extend. We will call our parent class Container and work on the core functionality that should be present in each concrete container. In the real world containers have a maximum amount of material which they will be able to hold, so we will first implement size constraints on our containers. Let's get our first unit test going:</p>
<pre class="brush: php;">class ContainerTest extends PHPUnit_Framework_TestCase

{

	public function testSizeOfContentsIsZeroOnStart()

	{

		$container = new Container();

		$this-&gt;assertEquals(0, $container-&gt;getSizeOfContents();

	}

}</pre>
<p>Now we must implement our Container class:</p>
<pre class="brush: php;">class Container

{

	public function getSizeOfContents()

	{

	}

}</pre>
<p>Obviously, this is going to fail when we test it, but in the spirit of TDD we will run the test anyway as follows:</p>
<pre class="brush: plain;">&gt; phpunit test-1.php

PHPUnit 3.3.3 by Sebastian Bergmann.

F

Time: 0 seconds

There was 1 failure:

1) testSizeOfContentsIsZeroOnStart(ContainerTest)

Failed asserting that &lt;null&gt; matches expected value &lt;integer:0&gt;.

/home/dev/modernphpworkflow/code/test-1.php:9

FAILURES!

Tests: 1, Assertions: 1, Failures: 1.</pre>
<p>This is really easy to fix so we will update the getSizeOfContents() method to the following:</p>
<pre class="brush: php;">public function getSizeOfContents()

{

	return 0;

}</pre>
<p>Now when we run our unit test we expect that our code will pass the test.</p>
<pre class="brush: plain;">&gt; phpunit test-1.php

PHPUnit 3.3.3 by Sebastian Bergmann.

.

Time: 0 seconds

OK (1 test, 1 assertion)</pre>
<p>This is the point where most people think test driven development is a waste of time. The code I wrote to pass the test is obviously not what the final code should be. In fact it is so simple that by writing it I have possibly proven that I have no idea what I am doing when I work on this project. However by religiously only writing code in your class that will cause the tests to pass will force you to think about what you are writing and how it will fill a need in the grand scheme of the project. Let's move on. We now know that when we first instantiate our container class that the container will tell us its size is 0. What happens when we add an object to the container? What will it report as its size then?</p>
<pre class="brush: php;">public function testGetSizeOfContainerAfterAddingObject()

{

	$container = new Container();

	$container-&gt;addObject('object1');

	$this-&gt;assertEquals(1, $container-&gt;getSizeOfContents());

}
</pre>
<pre class="brush: plain;">&gt; phpunit test-2.php

PHPUnit 3.3.3 by Sebastian Bergmann.

.F

Time: 0 seconds

There was 1 failure:

1) testGetSizeOfContainerAfterAddingObject(ContainerTest)

Failed asserting that &lt;integer:0&gt; matches expected value &lt;integer:1&gt;.

/home/jcarouth/modernphpworkflow/code/test-2.php:16

FAILURES!

Tests: 2, Assertions: 2, Failures: 1.</pre>
<p>Fixing our code base to pass the test will look like this:</p>
<pre class="brush: php;">class Container

{

	private $_contents;

	public function __construct()

	{

		$this-&gt;_contents = array();

	}

	public function getSizeOfContents()

	{

		return count($this-&gt;_contents);

	}

	public function addObject($obj)

	{

		$this-&gt;_contents[] = $obj;

	}

}</pre>
<p>You can see that we have enforced this behavior with our tests. In the second test we wrote we know that on instantiation the size of the container must be 0. Therefore adding a single object to the container would require that the size of the container increase by a one. We could, for good measure, amend our test to test the addition of increasing numbers of items and the effect these additions have on the size of the container. However we know that the relationship is a one to one. One additional object added means the size increases by one.</p>
<p>Back to the size constraint; our container must be able to know its maximum size and know whether the item(s) being added will exceed that size. Our first stab might look like this:</p>
<pre class="brush: php;">public function testGetSetMaximumSize()

{

	$container = new Container();

	$this-&gt;assertNull($container-&gt;getMaximumSize());

	$container-&gt;setMaximumSize(5);

	$this-&gt;assertEquals(5, $this-&gt;getMaximumSize());

}</pre>
<p>However, we must think about the users of this container class. Is it reasonable to force the code to set the maximum value in the manner shown? I do not think I would want to use the container object if it required adding the line $container-&gt;setMaximumSize(5); in all code that uses a maximum size. I would much rather pass the size in as a configuration parameter. I'll change my test code to model this change in design:</p>
<pre class="brush: php;">public function testGetSetMaximumSize()

{

	$containerWithNoMax = new Container();

	$this-&gt;assertNull($container-&gt;getMaximumSize());

	$containerWithMax = new Container(array('max' =&gt; 5));

	$this-&gt;assertEquals(5, $this-&gt;getMaximumSize());

}</pre>
<p>This test is run. It fails. Now we write the code to pass the test:</p>
<pre class="brush: php;">class Container

{

        private $_contents;

        private $_options;

	public function __construct($options = null)

	{

		$this-&gt;setOptions($options)

		$this-&gt;contents = array();

	}

	public function setOptions($options)

	{

		if(null === $options)

			$options = array();

		$defaults = array(

			'max' =&gt; null

		);

		$options = array_merge($options, $defaults);

		$this-&gt;options = $options;

	}

	public function getMaximumSize()

	{

		return $this-&gt;_options['max'];

	}

	//rest of code

}</pre>
<p>You might have noticed, but I am betting that you did not catch the mistake in the above code. On line 22 of the previous listing I used the array_merge() function to populate the options array with the default options for cases where the user of the code does not want to override any/all of the options. However, in my haste to get the code out I forgot that the values that appear in the latter of the parameters to array_merge will overwrite values with the same key in previous parameters. Thus the code above will not honor the options given to it. Be honest with yourself; suppose it is a Friday and you have been working long hours lately to get to feature complete, would you have caught this mistake without wasting anymore time than it takes to run the unit test? It is possible, but the unit test code caught it immediately and I was able to correct the code saving myself debugging time in the future.</p>
<pre class="brush: plain;">&gt; phpunit test-2.php

PHPUnit 3.3.3 by Sebastian Bergmann.

..F

Time: 0 seconds

There was 1 failure:

1) testGetSetMaximumSize(ContainerTest)

Failed asserting that &lt;null&gt; matches expected value &lt;integer:5&gt;.

/home/jcarouth/modernphpworkflow/code/test-2.php:24

FAILURES!

Tests: 3, Assertions: 4, Failures: 1.</pre>
<p>For example's sake we are going to make our Container class throw an exception if an object is added to the container which would put the container over maximum capacity; whether this is truly exceptional behavior is a matter for another day. PHPUnit allows several ways to test the exceptions that are expected in your code. I am partial to using the setExpectedException() method. When attempting to add an object we want our code to throw an ContainerAtMaximumException which in this example is assumed to simply be a subclass of the standard PHP Exception class. In the ContainerTest suite we add a test method that expects an exception to be raised, run the test, correct the failure by throwing the exception, and then run the test to verify our code behaves according to the contract.</p>
<pre class="brush: php;">public function testAddTooManyObjectsThrowsException()

{

	$container = new Container(array('max' =&gt; 1));

	$container-&gt;add('valid');

	$this-&gt;setExpectedException('ContainerAtMaximumException');

	$container-&gt;add('over');

}</pre>
<p>I mentioned there are additional options in PHPUnit for testing exceptions. The first is similar to the method above, but involves a special comment, and the other is a more traditional approach.</p>
<pre class="brush: php;">/**

 * @expectedException ContainerAtMaximumException

 */

public function testAddTooManyObjectsThrowsException()

{

	//code that should throw exception

}

public function testAddTooManyObjectsThrowsException()

{

	try

	{

		//code that should throw exception

	}

	catch(ContainerAtMaximumException $e)

	{

		return;

	}

	$this-&gt;fail('Expected exception ContainerAtMaximumException');

}</pre>
<p>I prefer the first method introduced because the comment method seems easy to lose in larger test suites and the last method is a lot more typing. Yes, like most programmers I am lazy.</p>
<p>I would like to take this time to indoctrinate with the mantra that should closely match your process when developing projects especially on projects with more than one developer: "Code. Test. Update. Test. Check in. Repeat." What this means is that when developing you should write the code for the feature you are developing or the bug you are fixing and then test your solution. Once you are satisfied with the solution you should update your working copy of the code from your source code management system and then run the tests again. Once these all pass you are clear to check in your code and smile because you did your part in not breaking the build that is coming in the next section.</p>
<h1>The Catalyst: Phing</h1>
<p>At this point we have a small code base that is tested via unit tests, but we are relying on human interaction to run the tests. As a developer there is one thing you should be painfully aware of: human interaction will fail. Thus as developers we have created tools that will aid in completed complex tasks with little-to-no effort on our part. Phing is one of those tools. If you are not familiar with project building--which I will have to admit is not something that is commonly brought up when speaking of PHP development--at the basic level building a project consists of running a series of tasks to package, test, deploy, document, etc your code base.</p>
<p>Phing is based on Apache Ant and uses XML build files to trigger tasks that are written in PHP classes which handle everything from packaging (PEAR packages included) to running PHPLint to filesystem operations to running unit tests. The latter is the most interesting for the purposes of this article, but the power of Phing is something that should not be overlooked.</p>
<p>It is common practice in development teams to have a "snapshot" build on a regular basis that represents the current state of the code that is checked in the source control. It is not unreasonable that the code in a build contains bugs but a problem is present if the code inside source control is extremely unstable or contains fatal errors. With the unit tests most of the fatal errors will be caught prior to check in (remember our mantra from the last section) and thus will not be in the build. However per Murphy's Law it is inevitable that bugs will creep into the build by a missed part of the mantra. Suppose that a person completes their feature, runs the tests, and then checks in their code. In the time this person was working on their feature, another developer checked in a patch to a bug in a library used by the first developer in the new feature. Without the update and unit tests this fact is overlooked until the time comes for the daily build. Once the build runs (sans unit tests, mind you) the snapshot is deployed to the quality assurance team who then discovers the fatal error and cannot test the new feature or the bug fixes that are effected by the error. This is where Phings ability to conditionally halt the build if unit tests do not pass becomes invaluable.</p>
<p>All this talk of tasks and running unit tests makes Phing sound like a complicated beast. Truthfully it is a complicated beast but because of the simple complexity of XML we are able to tame Phing with a simple text editor. For our build we merely want to run the unit tests contained in the tests directory and then package the code inside library into a zip file called build-latest.zip. These are modest tasks that could probably be scripted in a matter of minutes but because Phing is such an extensible tool we are going to use it so that adoption is not a hassle down the line.</p>
<p>To create the build script we need a PHPUnit task, a Zip task, and the FileSet type. We add these tasks inside a build target which will be called, creatively, "build."</p>
<pre class="brush: xml;">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;

&lt;project basedir=&quot;.&quot; default=&quot;build&quot; name=&quot;container&quot;&gt;

   &lt;target name=&quot;build&quot; description=&quot;Runs the test suite and creates the latest build&quot;&gt;

       &lt;phpunit haltonfailure=&quot;true&quot; haltonerror=&quot;true&quot;&gt;

           &lt;batchtest&gt;

               &lt;fileset dir=&quot;tests&quot;&gt;

                   &lt;include name=&quot;*Test.php&quot; /&gt;

               &lt;/fileset&gt;

           &lt;/batchtest&gt;

       &lt;/phpunit&gt;

	&lt;zip destfile=&quot;builds/build-latest.zip&quot;&gt;

		&lt;fileset dir=&quot;library&quot;&gt;

			&lt;include name=&quot;**/**&quot; /&gt;

		&lt;/fileset&gt;

	&lt;/zip&gt;

   &lt;/target&gt;

&lt;/project&gt;
</pre>
<p>This build file, upon being run by the command "phing build," will run all tests inside the directory tests that match the pattern *Test.php. If all tests pass, the script will continue on and create, if necessary, a zip file that represents the latest code. The beauty is that if any unit test fails or has an error the build-latest.zip file will not be updated.</p>
<p>We now have test code that represents a contract with which our library code must comply and a build script which ensures that our contract is enforced upon the library code on a regular basis. This, however, merely skims the surface of the capabilities of Phing. One of my favorite tasks in Phing is the CoverageReport task. Coupled with the phpunit task (assuming the attribute codecoverage is set to true) this task is capable of generating a report of the amount of code in the library that is covered by the unit tests. While it is theoretically impossible to achieve 100% code coverage (and even if the report says you have 100% you may not really have total coverage) it is encouraging to know that at a minimum the lines in your library are being run by the unit tests and should be functional according to that contract.</p>
<p>The only problem left to solve is that we must remember to run build script. We could add a scheduled task that would handle this for us, but suppose we want something more advanced. A scheduled task will run the build on the given interval no matter what. Chances are during the lifetime of a project there will be times when no work is being completed on that project so running a build script does not make sense. We need a way to determine if changes have been made to the project which would warrant a build. Enter Xinc, a continuous integration server written in PHP5.</p>
<h1>Automation: Xinc Continuous Integration Server</h1>
<p>To fully reap the benefits afforded by a continuous integration server such as Xinc one must understand the problem the server attempts to solve. In a multi-developer environment features, dependencies, and even bugs are added at an alarming pace. The difficulty associated with ensuring that a project will function when compiled together is what is being termed integration. Continuous, as it implies, means frequently occurring. Therefore a continuous integration server handles compiling the code base, external libraries, and other dependencies together on a frequent basis. The benefit should be obvious at this point. Combined with the tools outlined in the previous section a continuous integration server can automatically trigger build scripts to run when it is known that changes have been made to the code base.</p>
<p>In our theatrical number Xinc represents the director that gives cues to Phing who then runs through the lines of the test suite to ensure that the code is functional in regards to the requirements. But that is not all Xinc is capable of. Xinc holds historical data regarding the builds that have been performed on the project including metrics about unit tests, number of passed builds and failed builds, and can even create deliverables in the form of archive files. The power of a CI server is in the rapid feedback provided to all developers, product managers, project managers, etc involved in a project.</p>
<p>As mentioned, obtaining Xinc CI server is easily accomplished through PEAR. After installed per the directions on the website (http://xinc.googlecode.com) you will notice that you have a daemon that runs on your build server as well as a web front end to the CI server. The daemon is responsible for checking your configured projects for changes according to the schedule, running the builders associated with the project, and then running any publishers for the project being integrated. Bear with me while we knock out the terminology.</p>
<p>Projects are defined using XML configuration files. These files are then parsed by the Xinc daemon and appropriate actions taken according to the rules set forth in the XML file. The most common configuration sets up a project that is given a schedule property, a modificationset, at least one builder, and a success and failure publisher as outlined by the following configuration file:</p>
<pre class="brush: xml;">&lt;?xml version=&quot;1.0&quot;?&gt;

&lt;xinc engine=&quot;Sunrise&quot;&gt;

	&lt;project name=&quot;ExampleProject&quot;&gt;

		&lt;property name=&quot;dir&quot; value=&quot;${projectdir}/${project.name}&quot; /&gt;

		&lt;schedule interval=&quot;240&quot; /&gt;

		&lt;modificationset&gt;

			&lt;svn directory=&quot;${dir}&quot; update=&quot;true&quot; /&gt;

		&lt;/modificationset&gt;

		&lt;builders&gt;

			&lt;phingbuilder buildfile=&quot;${dir}/build.xml&quot; /&gt;

		&lt;/builders&gt;

		&lt;publishers&gt;

			&lt;onfailure&gt;

				&lt;email to=&quot;you@email.com&quot; subject=&quot;Build failed&quot; message=&quot;Build of project failed&quot; /&gt;

			&lt;/onfailure&gt;

			&lt;onsuccess&gt;

				&lt;email to=&quot;you@email.com&quot; subject=&quot;Build success&quot; message=&quot;Build of project was successful&quot; /&gt;

			&lt;/onsuccess&gt;

		&lt;/publishers&gt;

	&lt;/project&gt;

&lt;/xinc&gt;</pre>
<p>Starting inside the project element, the first element encountered is a property element. Properties become handy to simplify using long or complex values throughout the remainder of the file. In this example we set a property called dir which makes use of two of the built-in properties to compile the directory that represents the working copy of our project "ExampleProject." The value, in our example, for the dir property will be /var/xinc/projects/ExampleProject. Other useful built-in properties include build.number, and build.timestamp. As you will see later, these properties can be used to generate deliverables or snapshots as we discussed earlier in the section regarding Phing.</p>
<p>The schedule element, as its name might imply, tells the Xinc daemon the frequency that the repository should be checked for changes in seconds. In our example Xinc will check the repository every four minutes. If there is an update to the repository, the working copy in the project directory will be updated and the builders started. The schedule element is useless without the modificationset element because the modificationset element contains the information about what tasks can trigger a build. Currently Xinc support two modificationsets: buildalways and svn. The buildalways modificationset will always trigger a build on the interval by faking a positive modification. If we removed the svn element in our example and replaced it with the tag &lt;buildalways /&gt; every four minutes a build would be triggered. The svn modificationset will check the repository associated with the working copy located in the path given in the directory attribute for changes. If changes are detected, a build will be triggered. Optional attributes for the svn modificationset include a username and password attribute, and an update attribute. In our example, each time modifications are detected to the repository, our working copy will be updated with those changes.</p>
<p>The builders element contains all builder tasks or build scripts that will be run when modifications are detected. Currently the only supported build task is a Phing task. It is important to note that properties, such as the build.number property discussed above, available in Xinc configuration files will be available to phing build scripts as xinc.property (e.g. xinc.build.number). Keep this under consideration when writing build scripts that will be used by Xinc.</p>
<p>Our final element to the project is the publishers element. The main publishers available are phingpublisher, email, deliverable, artifact, and documentation. As their names imply a phingbuilder and email publisher will run a Phing script and send an email, respectively. The deliverable publisher is used to create a downloadable copy of the successfully built code base. Using an alias a build-latest.tar file, for example, can be created in addition to the specific build number file. Files created by the deliverable publisher will be available on the Xinc web interface. The artifact publisher is used to create build-specific reports or historical build information that will also be available for download on the web interface. Combined with running PHPUnit test code coverage analysis, this can be used to provide the code coverage report for each build. The documentation publisher will register a phpdocumentor directory and make it available on the web interface.</p>
<p>Each of the phingpublisher, email, deliverable, artifact, and documentation publishers can be children any of the onsuccess, onfailure, or onrecovery publishers. The children of the onsuccess publisher will only be executed when a build is successful. The opposite is true for the onfailure publisher. The onrecovery publisher executes its child publishers only when a failed build is recovered and is made successful.</p>
<p>Once you have decided which publishers you wish to run and have your project configuration file in the proper directory (on linux the default is /etc/xinc/conf.d) and the daemon is started you can head over to the Xinc web front end (which defaults to http://localhost:8080) and view your CI server. Assuming your configuration is correct you will notice your project listed and it should have a build status indicator (hopefully it is successful.)</p>
<h1>Conclusion</h1>
<p>The Modern PHP Workflow consists of tools that help answer the questions about the stability of your code and will enable you to continuously build successful products. With a PHPUnit test suite each line of your code serves a purpose and is proven time and again to function as intended, Phing helps you automate the process of running tests on code and packaging code for deployment or testing, and Xinc automates the integration of your work with your team member's work to provide instant feedback and create solid final products. This modern approach to development with PHP is proven to increase quality and even productivity.</p>
<div class="acc_license"><a href="http://creativecommons.org/licenses/by/3.0/"><img src="http://i.creativecommons.org/l/by/3.0/88x31.png" alt="by" /></a></div><!--<rdf:RDF xmlns="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="http://creativecommons.org/licenses/by/3.0/" /></Work><License rdf:about="http://creativecommons.org/licenses/by/3.0/"><requires rdf:resource="http://creativecommons.org/ns#Attribution" /><permits rdf:resource="http://creativecommons.org/ns#Reproduction" /><permits rdf:resource="http://creativecommons.org/ns#Distribution" /><permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><requires rdf:resource="http://creativecommons.org/ns#Notice" /></License></rdf:RDF>-->


Share:


	<a rel="nofollow"  target="_blank" href="http://www.printfriendly.com/print?url=http%3A%2F%2Fcarouth.com%2F2009%2F10%2F20%2Fthe-modern-php-workflow%2F&amp;partner=sociable" title="Print"><img src="http://carouth.com/wp-content/plugins/sociable/images/printfriendly.png" title="Print" alt="Print" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fcarouth.com%2F2009%2F10%2F20%2Fthe-modern-php-workflow%2F&amp;title=The%20Modern%20PHP%20Workflow&amp;bodytext=%5Bnote%5DThis%20article%20was%20originally%20published%20in%20November%202008%20by%20php%7Carchitect.%5B%2Fnote%5D%0D%0A%0D%0AOver%20time%20we%20have%20all%20seen%20projects%20that%20become%20great%20success%20stories%20and%20our%20fair%20share%20of%20projects%20that%20become%20epic%20failures.%20Some%20of%20this%20can%20be%20blamed%20on%20the" title="Digg"><img src="http://carouth.com/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fcarouth.com%2F2009%2F10%2F20%2Fthe-modern-php-workflow%2F&amp;title=The%20Modern%20PHP%20Workflow&amp;notes=%5Bnote%5DThis%20article%20was%20originally%20published%20in%20November%202008%20by%20php%7Carchitect.%5B%2Fnote%5D%0D%0A%0D%0AOver%20time%20we%20have%20all%20seen%20projects%20that%20become%20great%20success%20stories%20and%20our%20fair%20share%20of%20projects%20that%20become%20epic%20failures.%20Some%20of%20this%20can%20be%20blamed%20on%20the" title="del.icio.us"><img src="http://carouth.com/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fcarouth.com%2F2009%2F10%2F20%2Fthe-modern-php-workflow%2F&amp;t=The%20Modern%20PHP%20Workflow" title="Facebook"><img src="http://carouth.com/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.google.com/bookmarks/mark?op=edit&amp;bkmk=http%3A%2F%2Fcarouth.com%2F2009%2F10%2F20%2Fthe-modern-php-workflow%2F&amp;title=The%20Modern%20PHP%20Workflow&amp;annotation=%5Bnote%5DThis%20article%20was%20originally%20published%20in%20November%202008%20by%20php%7Carchitect.%5B%2Fnote%5D%0D%0A%0D%0AOver%20time%20we%20have%20all%20seen%20projects%20that%20become%20great%20success%20stories%20and%20our%20fair%20share%20of%20projects%20that%20become%20epic%20failures.%20Some%20of%20this%20can%20be%20blamed%20on%20the" title="Google Bookmarks"><img src="http://carouth.com/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fcarouth.com%2F2009%2F10%2F20%2Fthe-modern-php-workflow%2F&amp;title=The%20Modern%20PHP%20Workflow" title="Reddit"><img src="http://carouth.com/wp-content/plugins/sociable/images/reddit.png" title="Reddit" alt="Reddit" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fcarouth.com%2F2009%2F10%2F20%2Fthe-modern-php-workflow%2F&amp;title=The%20Modern%20PHP%20Workflow" title="StumbleUpon"><img src="http://carouth.com/wp-content/plugins/sociable/images/stumbleupon.png" title="StumbleUpon" alt="StumbleUpon" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=The%20Modern%20PHP%20Workflow%20-%20http%3A%2F%2Fcarouth.com%2F2009%2F10%2F20%2Fthe-modern-php-workflow%2F" title="Twitter"><img src="http://carouth.com/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>]]></content:encoded>
			<wfw:commentRss>http://carouth.com/2009/10/20/the-modern-php-workflow/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
