<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<feed xmlns="http://www.w3.org/2005/Atom">

	<title>Planet PHPUnit</title>
	<link rel="self" href="http://planet.phpunit.de/atom.xml"/>
	<link href="http://planet.phpunit.de/"/>
	<id>http://planet.phpunit.de/atom.xml</id>
	<updated>2010-03-15T00:00:33+00:00</updated>
	<generator uri="http://www.planetplanet.org/">Planet/2.0 +http://www.planetplanet.org</generator>

	<entry xml:lang="en">
		<title type="html">Stubbing Hard-Coded Dependencies</title>
		<link href="http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html"/>
		<id>http://sebastian-bergmann.de/archives/885-guid.html</id>
		<updated>2010-02-16T07:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;strong&gt;This article is part of a series on testing untestable code:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html&quot;&gt;Testing private methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html&quot;&gt;Testing code that uses singletons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html&quot;&gt;Stubbing static methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html&quot;&gt;Stubbing hard-coded dependencies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_test&quot;&gt;unit test&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Mock_Object&quot;&gt;mock objects&lt;/a&gt; can simulate the behavior of complex, real (non-mock) objects and are therefore useful when a real object is difficult or impossible to incorporate into a unit test.&lt;/p&gt;
&lt;p&gt;A mock object can be used anywhere in the program where the program expects an object of the mocked class. However, this only works as long as the object can be passed into the context where the original object is used.&lt;/p&gt;
&lt;p&gt;Consider the following example:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;require_once&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'Bar.php'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomethingElse&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;

&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Bar&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomethingElse&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'*'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;With the code above, it is impossible to run a unit test for the &lt;code&gt;Foo::doSomething()&lt;/code&gt; method without also creating an object of &lt;code&gt;Bar&lt;/code&gt;. As the method creates the object of &lt;code&gt;Bar&lt;/code&gt; itself, we cannot inject a mock object in its stead.&lt;/p&gt;
&lt;p&gt;In a perfect world, code such as the above could be refactored using &lt;a href=&quot;http://en.wikipedia.org/wiki/Dependency_Injection&quot;&gt;Dependency Injection&lt;/a&gt;:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;require_once&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'Bar.php'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;===&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Bar&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomethingElse&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;Unfortunately, this is not always possible (not because of technical reasons, though).&lt;/p&gt;
&lt;p&gt;This is where the &lt;code&gt;set_new_overload()&lt;/code&gt; function that is provided by the &lt;a href=&quot;http://github.com/sebastianbergmann/php-test-helpers&quot;&gt;test_helpers&lt;/a&gt; extension for the PHP Interpreter comes into play. It can be used to register a &lt;a href=&quot;http://www.php.net/manual/en/language.pseudo-types.php&quot;&gt;callback&lt;/a&gt; that is automatically invoked when the &lt;code&gt;new&lt;/code&gt; operator is executed:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;require_once&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'Foo.php'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FooTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;setUp&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getMock&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'Bar'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;name&amp;#160;of&amp;#160;class&amp;#160;to&amp;#160;mock&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'doSomethingElse'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;list&amp;#160;of&amp;#160;methods&amp;#160;to&amp;#160;mock&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;constructor&amp;#160;arguments&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'BarMock'&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;name&amp;#160;for&amp;#160;mocked&amp;#160;class&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;set_new_overload&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'newCallback'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;tearDown&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;unset_new_overload&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;newCallback&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$className&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$className&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;case&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'Bar'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'BarMock'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$className&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testDoSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;Lets run this unit test:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre&gt;PHPUnit 3.4.10 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 7.50Mb

OK (1 test, 2 assertions)&lt;/pre&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;Note that there is no &lt;code&gt;*&lt;/code&gt; (printed from &lt;code&gt;Bar::doSomethingElse()&lt;/code&gt;) in the output above.&lt;/p&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Sharing Fixture Between Tests</title>
		<link href="http://sebastian-bergmann.de/archives/884-Sharing-Fixture-Between-Tests.html"/>
		<id>http://sebastian-bergmann.de/archives/884-guid.html</id>
		<updated>2010-02-14T09:40:10+00:00</updated>
		<content type="html">&lt;p&gt;There are few good reasons to share fixtures between tests, but in most cases the need to share a fixture between tests stems from an unresolved design problem.&lt;/p&gt;
&lt;p&gt;A good example of a fixture that makes sense to share across several tests is a database connection: you log into the database once and reuse the database connection instead of creating a new connection for each test. This makes your tests run faster.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit 3.5&lt;/a&gt; removes the &lt;a href=&quot;http://www.phpunit.de/manual/3.4/en/fixtures.html#fixtures.sharing-fixture&quot;&gt;fixture sharing&lt;/a&gt; feature of the &lt;code&gt;TestSuite&lt;/code&gt; class. It was tedious to use this feature as it required the usage of a custom &lt;code&gt;TestSuite&lt;/code&gt; class in addition to the test case class. Furthermore, its implementation was a &quot;hack&quot;.&lt;/p&gt;
&lt;p&gt;PHPUnit 3.4 introduced the &lt;code&gt;setUpBeforeClass()&lt;/code&gt; and &lt;code&gt;tearDownAfterClass()&lt;/code&gt; template methods that can be used in a test case class. These methods allow a much cleaner and simpler implementation of fixture sharing between tests of the same test case class:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;DatabaseTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$dbh&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;setUpBeforeClass&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$dbh&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PDO&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'sqlite::memory:'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;tearDownAfterClass&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$dbh&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;The example above uses the &lt;code&gt;setUpBeforeClass()&lt;/code&gt; and &lt;code&gt;tearDownAfterClass()&lt;/code&gt; template methods to connect to the database before the test case class' first test and to disconnect from the database after the last test of the test case, respectively.&lt;/p&gt;
&lt;p&gt;It cannot be emphasized enough that &lt;a href=&quot;http://www.phpunit.de/manual/3.5/en/fixtures.html#fixtures.sharing-fixture&quot;&gt;sharing fixtures&lt;/a&gt; between tests reduces the value of the tests. The underlying design problem is that objects are not loosely coupled. You will achieve better results solving the underlying design problem and then writing tests using &lt;a href=&quot;http://www.phpunit.de/manual/current/en/test-doubles.html&quot;&gt;test doubles&lt;/a&gt;, than by creating dependencies between tests at runtime and ignoring the opportunity to improve your design.&lt;/p&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Stubbing and Mocking Static Methods</title>
		<link href="http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html"/>
		<id>http://sebastian-bergmann.de/archives/883-guid.html</id>
		<updated>2010-02-12T05:30:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;strong&gt;This article is part of a series on testing untestable code:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html&quot;&gt;Testing private methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html&quot;&gt;Testing code that uses singletons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html&quot;&gt;Stubbing static methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html&quot;&gt;Stubbing hard-coded dependencies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;With PHPUnit 3.5 it will be possible to stub and mock static methods.&lt;/p&gt;
&lt;p&gt;Consider the class &lt;code&gt;Foo&lt;/code&gt;:&lt;/p&gt;

&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;helper&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;helper&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'foo'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;When testing &lt;code&gt;Foo::doSomething()&lt;/code&gt; we want to decouple it from its dependency &lt;code&gt;Foo::helper()&lt;/code&gt;. With PHPUnit 3.5 and PHP 5.3 as well as consistent use of late static binding (using &lt;code&gt;static::&lt;/code&gt; instead of &lt;code&gt;self::&lt;/code&gt;) the following is possible:&lt;/p&gt;

&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FooTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testDoSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getMockClass&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'Foo'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;name&amp;#160;of&amp;#160;class&amp;#160;to&amp;#160;mock&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'helper'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;list&amp;#160;of&amp;#160;methods&amp;#160;to&amp;#160;mock&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$class&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;staticExpects&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'helper'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;will&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;returnValue&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'bar'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'bar'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$class&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;The new &lt;code&gt;staticExpects()&lt;/code&gt; method works similar to the non-static &lt;code&gt;expects()&lt;/code&gt; variant.&lt;/p&gt;

&lt;p&gt;This approach only works for the stubbing and mocking of static method calls where &lt;em&gt;caller&lt;/em&gt; and &lt;em&gt;callee&lt;/em&gt; are in the same class. This is because &lt;a href=&quot;http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/&quot;&gt;static methods are death to testability&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;&quot;&lt;em&gt;Unit-Testing needs seams, seams is where we prevent the execution of normal code path and is how we achieve isolation of the class under test. Seams work through polymorphism, we override/implement class/interface and then wire the class under test differently in order to take control of the execution flow. With static methods there is nothing to override. Yes, static methods are easy to call, but if the static method calls another static method there is no way to override the called method dependency.&lt;/em&gt;&quot;&lt;/blockquote&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Testing Code That Uses Singletons</title>
		<link href="http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html"/>
		<id>http://sebastian-bergmann.de/archives/882-guid.html</id>
		<updated>2010-02-11T14:45:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;strong&gt;This article is part of a series on testing untestable code:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html&quot;&gt;Testing private methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html&quot;&gt;Testing code that uses singletons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html&quot;&gt;Stubbing static methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html&quot;&gt;Stubbing hard-coded dependencies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;I frequently quote &lt;a href=&quot;http://misko.hevery.com/&quot;&gt;Mi&#353;ko Hevery&lt;/a&gt; with&lt;/p&gt;
&lt;blockquote&gt;&quot;&lt;em&gt;&lt;a href=&quot;http://googletesting.blogspot.com/2008/05/tott-using-dependancy-injection-to.html&quot;&gt;It is hard to test code that uses singletons.&lt;/a&gt;&lt;/em&gt;&quot;&lt;/blockquote&gt;
&lt;p&gt;And then my audience asks me ...&lt;/p&gt;
&lt;h4&gt;Why is it hard to test code that uses singletons?&lt;/h4&gt;
&lt;p&gt;Lets have a look at the default implementation of the &lt;a href=&quot;http://en.wikipedia.org/wiki/Singleton_pattern&quot;&gt;Singleton&lt;/a&gt; design pattern in PHP:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;__clone&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;===&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;The code above declares a class that cannot be instantiated (or cloned) by a client using the &lt;code&gt;new&lt;/code&gt; (or &lt;code&gt;clone&lt;/code&gt;) operator(s). To get a reference to the only instance of the class one has to use the static method &lt;code&gt;getInstance()&lt;/code&gt;. Usually the code that uses the Singleton (which we will refer to as &lt;em&gt;client&lt;/em&gt;) is strongly coupled to the &lt;code&gt;getInstance()&lt;/code&gt; method:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Client&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;It is impossible to write a test for the &lt;code&gt;doSomething()&lt;/code&gt; method without also invoking the singleton's &lt;code&gt;getInstance()&lt;/code&gt; method. This means that we cannot get a fresh instance of the &lt;code&gt;Singleton&lt;/code&gt; class and thus have no guarantee that there are no side effects in multiple tests that interact with the singleton.&lt;/p&gt;
&lt;h4&gt;Dependency Injection&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Dependency_Injection&quot;&gt;Dependency Injection&lt;/a&gt; can help with decoupling the client from the &lt;code&gt;getInstance()&lt;/code&gt; method:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Client&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;===&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;Instead of unconditionally invoking the &lt;code&gt;getInstance()&lt;/code&gt; method inside the &lt;code&gt;doSomething()&lt;/code&gt; we can now optionally pass in an instance of the &lt;code&gt;Singleton&lt;/code&gt; class. This allows us to pass in a &lt;em&gt;test-specific equivalent&lt;/em&gt; such as a &lt;em&gt;mock object&lt;/em&gt; or &lt;em&gt;stub&lt;/em&gt;:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;ClientTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testSingleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getMock&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'Singleton'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;name&amp;#160;of&amp;#160;class&amp;#160;to&amp;#160;mock&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;list&amp;#160;of&amp;#160;methods&amp;#160;to&amp;#160;mock&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;constructor&amp;#160;arguments&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;name&amp;#160;for&amp;#160;mocked&amp;#160;class&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;do&amp;#160;not&amp;#160;invoke&amp;#160;constructor&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&amp;#160;configure&amp;#160;$singleton&amp;#160;...&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$client&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Client&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$client&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$singleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;//&amp;#160;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;h4&gt;Alternative Singleton Implementations&lt;/h4&gt;
&lt;p&gt;Either as an alternative or in addition to rewriting the clients to optionally accept an instance of the &lt;code&gt;Singleton&lt;/code&gt; class as an argument, we can also rewrite the &lt;code&gt;Singleton&lt;/code&gt; class to make testing easier.&lt;/p&gt;
&lt;h5&gt;Resettable Singleton&lt;/h5&gt;
&lt;p&gt;The first approach is to add a &lt;code&gt;reset()&lt;/code&gt; method to the &lt;code&gt;Singleton&lt;/code&gt; class:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;__clone&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;===&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;Invoking the &lt;code&gt;reset()&lt;/code&gt; method causes the &lt;code&gt;getInstance()&lt;/code&gt; method to create a fresh object of the &lt;code&gt;Singleton&lt;/code&gt; class the next time it is called.&lt;/p&gt;
&lt;h5&gt;Singleton with Test Context&lt;/h5&gt;
&lt;p&gt;The second approach is to add a &lt;em&gt;testing context&lt;/em&gt; to the &lt;code&gt;Singleton&lt;/code&gt; class:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$testing&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;__construct&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;final&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;__clone&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;===&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;||&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$testing&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Singleton&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$uniqueInstance&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;Setting &lt;code&gt;Singleton::$testing = TRUE;&lt;/code&gt; causes the &lt;code&gt;getInstance()&lt;/code&gt; method to create a fresh object of the &lt;code&gt;Singleton&lt;/code&gt; class each time it is called.&lt;/p&gt;
&lt;h4&gt;PHPUnit Can Help, Too&lt;/h4&gt;
&lt;p&gt;PHPUnit has a &lt;a href=&quot;http://www.phpunit.de/manual/current/en/fixtures.html#fixtures.global-state&quot;&gt;backup/restore mechanism for static attributes of classes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is yet another feature of PHPUnit that makes the testing of code that uses global state (which includes, but is not limited to, &lt;a href=&quot;http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html&quot;&gt;global and superglobal variables&lt;/a&gt; as well as static attributes of classes) easier.&lt;/p&gt;
&lt;h4&gt;Just Because You Can, Does Not Mean You Should&lt;/h4&gt;
&lt;p&gt;Yes, it is possible write testable code that uses singletons.&lt;br /&gt;This does not mean, however, that you should use them without thinking twice.&lt;/p&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Testing Your Privates</title>
		<link href="http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html"/>
		<id>http://sebastian-bergmann.de/archives/881-guid.html</id>
		<updated>2010-02-09T12:00:59+00:00</updated>
		<content type="html">&lt;p&gt;&lt;strong&gt;This article is part of a series on testing untestable code:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html&quot;&gt;Testing private methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/882-Testing-Code-That-Uses-Singletons.html&quot;&gt;Testing code that uses singletons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html&quot;&gt;Stubbing static methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html&quot;&gt;Stubbing hard-coded dependencies&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;No, not &lt;a href=&quot;http://en.wikipedia.org/wiki/Sex_organ&quot;&gt;those privates&lt;/a&gt;. If you need help with those, &lt;a href=&quot;http://oreilly.com/catalog/9780596801755/&quot;&gt;this book&lt;/a&gt; might help.&lt;/p&gt;
&lt;p&gt;One question I get over and over again when talking about &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_Testing&quot;&gt;Unit Testing&lt;/a&gt; is this:&lt;/p&gt;
&lt;blockquote&gt;&quot;&lt;em&gt;How do I test the private attributes and methods of my objects?&lt;/em&gt;&quot;&lt;/blockquote&gt;
&lt;p&gt;Lets assume we have a class &lt;code&gt;Foo&lt;/code&gt;:
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'baz'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomethingPrivate&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomethingPrivate&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'blah'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;Before we explore how &lt;code&gt;protected&lt;/code&gt; and &lt;code&gt;private&lt;/code&gt; attributes and methods can be tested directly, lets have a look at how they can be tested indirectly.&lt;/p&gt;
&lt;p&gt;The following test calls the &lt;code&gt;testDoSomething()&lt;/code&gt; method which in turn calls the &lt;code&gt;doSomethingPrivate()&lt;/code&gt; method:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FooTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*&amp;#160;@covers&amp;#160;Foo::doSomething&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*&amp;#160;@covers&amp;#160;Foo::doSomethingPrivate&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testDoSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'blah'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$foo&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;The test above assumes that &lt;code&gt;testDoSomething()&lt;/code&gt; only works correctly when &lt;code&gt;testDoSomethingPrivate()&lt;/code&gt; works correctly. This means that we have indirectly tested &lt;code&gt;testDoSomethingPrivate()&lt;/code&gt;. The problem with this approach is that when the test fails we do not know directly where the root cause for the failure is. It could be in either &lt;code&gt;testDoSomething()&lt;/code&gt; or &lt;code&gt;testDoSomethingPrivate()&lt;/code&gt;. This makes the test less valuable.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt; supports reading &lt;code&gt;protected&lt;/code&gt; and &lt;code&gt;private&lt;/code&gt; attributes through the &lt;code&gt;PHPUnit_Framework_Assert::readAttribute()&lt;/code&gt; method. Convenience wrappers such as &lt;code&gt;PHPUnit_Framework_TestCase::assertAttributeEquals()&lt;/code&gt; exist to express assertions on &lt;code&gt;protected&lt;/code&gt; and &lt;code&gt;private&lt;/code&gt; attributes:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FooTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testPrivateAttribute&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertAttributeEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'baz'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;expected&amp;#160;value&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'bar'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;attribute&amp;#160;name&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/*&amp;#160;object&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;PHP 5.3.2 introduces the &lt;code&gt;ReflectionMethod::setAccessible()&lt;/code&gt; method to allow the invocation of &lt;code&gt;protected&lt;/code&gt; and &lt;code&gt;private&lt;/code&gt; methods through the Reflection API:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;FooTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*&amp;#160;@covers&amp;#160;Foo::doSomethingPrivate&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testPrivateMethod&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$method&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;ReflectionMethod&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'Foo'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'doSomethingPrivate'&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$method&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;setAccessible&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'blah'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$method&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;invoke&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;p&gt;In the test above we directly test &lt;code&gt;testDoSomethingPrivate()&lt;/code&gt;. When it fails we immediately know where to look for the root cause.&lt;/p&gt;
&lt;p&gt;I agree with Dave Thomas and Andy Hunt, who write in their book &quot;Pragmatic Unit Testing&quot;:&lt;/p&gt;
&lt;blockquote&gt;&quot;&lt;em&gt;In general, you don't want to break any encapsulation for the sake of testing (or as Mom used to say, &quot;don't expose your privates!&quot;). Most of the time, you should be able to test a class by exercising its public methods. If there is significant functionality that is hidden behind private or protected access, that might be a warning sign that there's another class in there struggling to get out.&lt;/em&gt;&quot;&lt;/blockquote&gt;
&lt;p&gt;So: Just because the testing of &lt;code&gt;protected&lt;/code&gt; and &lt;code&gt;private&lt;/code&gt; attributes and methods is possible does not mean that this is a &quot;good thing&quot;.&lt;/p&gt;&lt;/p&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">phpUnderControl 0.5.1 released</title>
		<link href="http://www.manuel-pichler.de/archives/79-phpUnderControl-0.5.1-released.html"/>
		<id>http://www.manuel-pichler.de/archives/79-guid.html</id>
		<updated>2010-01-31T20:16:35+00:00</updated>
		<content type="html">&lt;p&gt;
  Today I have released &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2246&amp;entry_id=79&quot; title=&quot;http://phpundercontrol.org&quot;&gt;phpUnderControl&lt;/a&gt; version &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2247&amp;entry_id=79&quot; title=&quot;http://github.com/manuelpichler/phpUnderControl/tree/0.5.1&quot;&gt;0.5.1&lt;/a&gt;. It's a bug fix release that closes several issues open since a long time. First of all I would like to thank &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2248&amp;entry_id=79&quot; title=&quot;http://twitter.com/proofek&quot;&gt;Sebastian Marek&lt;/a&gt; who was the main contributor to this releases, so a big thankyou to you.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Now phpUnderControl should work with &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2265&amp;entry_id=79&quot; title=&quot;http://cruisecontrol.sourceforge.net&quot;&gt;CruiseControl 2.8.3&lt;/a&gt;. Thanks to Mike van Riel who provided some hints on this issue in a &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2249&amp;entry_id=79&quot; title=&quot;http://manuel-pichler.de/archives/69-phpUnderControl-0.5.0-released.html#c350&quot;&gt;blog comment&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Fixed &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2250&amp;entry_id=79&quot; title=&quot;http://www.phpunit.de/ticket/983&quot;&gt;#983&lt;/a&gt;: Graph unitests throw fatal error when ezComponents not available.&lt;/li&gt;
  &lt;li&gt;Fixed &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2251&amp;entry_id=79&quot; title=&quot;http://www.phpunit.de/ticket/966&quot;&gt;#966&lt;/a&gt;: phpcs-details.xsl not showing file name.&lt;/li&gt;
  &lt;li&gt;Closed &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2252&amp;entry_id=79&quot; title=&quot;http://www.phpunit.de/ticket/863&quot;&gt;#863&lt;/a&gt;: Destination option is now deprecated.&lt;/li&gt;
  &lt;li&gt;Fixed &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2253&amp;entry_id=79&quot; title=&quot;http://www.phpunit.de/ticket/862&quot;&gt;#862&lt;/a&gt;: Command line switches without parameter don't work.&lt;/li&gt;
  &lt;li&gt;Fixed &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2254&amp;entry_id=79&quot; title=&quot;http://www.phpunit.de/ticket/861&quot;&gt;#861&lt;/a&gt;: Password is used as username in check outs. This patch was supplied by Thorsten Daners via e-mail.&lt;/li&gt;
  &lt;li&gt;Fixed &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2255&amp;entry_id=79&quot; title=&quot;http://www.phpunit.de/ticket/734&quot;&gt;#734&lt;/a&gt;: Now the build dropdown redirects to the correct build uri.&lt;/li&gt;
  &lt;li&gt;Implemented &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2256&amp;entry_id=79&quot; title=&quot;http://www.phpunit.de/ticket/703&quot;&gt;#703&lt;/a&gt;: PHPUnit test results are now the first entry on the project overview page.&lt;/li&gt;
  &lt;li&gt;Fixed &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2257&amp;entry_id=79&quot; title=&quot;http://www.phpunit.de/ticket/700&quot;&gt;#700&lt;/a&gt;: Throw an exception when the specified project does not exist.&lt;/li&gt;
  &lt;li&gt;Implemented &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2258&amp;entry_id=79&quot; title=&quot;http://www.phpunit.de/ticket/675&quot;&gt;#675&lt;/a&gt;: Use &quot;php -l&quot; for lint checking and not PHPUnit.&lt;/li&gt;
  &lt;li&gt;Implemented &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2259&amp;entry_id=79&quot; title=&quot;http://www.phpunit.de/ticket/625&quot;&gt;#625&lt;/a&gt;: Integrate PHP_Depend results.&lt;/li&gt;
&lt;/ul&gt;

&lt;br /&gt;
&lt;p&gt;
  Beside the new release some more things have changed. From now on the phpUnderControl development is hosted on &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2260&amp;entry_id=79&quot; title=&quot;http://github.com&quot;&gt;github&lt;/a&gt;. This means that from now on the latest version of phpUnderControl can be obtained with the following command:
&lt;/p&gt;

&lt;pre&gt;
mapi@arwen ~ $ git clone \
               git://github.com/manuelpichler/phpUnderControl.git
&lt;/pre&gt;

&lt;p&gt;
Additionally we have moved the phpUnderControl's PEAR Channel Server from &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2261&amp;entry_id=79&quot; title=&quot;http://pear.phpunit.de&quot;&gt;pear.phpunit.de&lt;/a&gt; to its own server &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2262&amp;entry_id=79&quot; title=&quot;http://pear.phpundercontrol.org&quot;&gt;pear.phpundercontrol.org&lt;/a&gt;. At this point I would like to thank &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2263&amp;entry_id=79&quot; title=&quot;http://sebastian-bergmann.de/&quot;&gt;Sebastian&lt;/a&gt; for providing phpUnderControl's infrastructure under the &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2264&amp;entry_id=79&quot; title=&quot;http://phpun.it&quot;&gt;PHPUnit umbrella&lt;/a&gt; for the last three years.
&lt;/p&gt;

&lt;pre&gt;
mapi@arwen ~ $ pear uninstall phpunit/phpUnderControl
mapi@arwen ~ $ pear channel-discover pear.phpundercontrol.org
mapi@arwen ~ $ pear install --alldeps phpuc/phpUnderControl-beta
Starting to download phpUnderControl-0.5.1.tgz (539,717 bytes)
..........................................done: 539,717 bytes
install ok: channel://pear.phpundercontrol.org/phpUnderControl-0.5.1
&lt;/pre&gt;</content>
		<author>
			<name>Manuel Pichler</name>
			<email>nospam@example.com</email>
			<uri>http://www.manuel-pichler.de/</uri>
		</author>
		<source>
			<title type="html">Manuel Pichler - phpundercontrol</title>
			<subtitle type="html">Trust is good, (phpUnder)Control is better.</subtitle>
			<link rel="self" href="http://manuel-pichler.de/feeds/categories/10-phpundercontrol.rss"/>
			<id>http://manuel-pichler.de/feeds/categories/10-phpundercontrol.rss</id>
			<updated>2010-02-01T05:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">CRAP in PHPUnit 3.5</title>
		<link href="http://sebastian-bergmann.de/archives/877-CRAP-in-PHPUnit-3.5.html"/>
		<id>http://sebastian-bergmann.de/archives/877-guid.html</id>
		<updated>2010-01-12T09:30:00+00:00</updated>
		<content type="html">&lt;p&gt;For the upcoming &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit 3.5&lt;/a&gt;, I have factored out all code that is related to &lt;a href=&quot;http://en.wikipedia.org/wiki/Code_coverage&quot;&gt;code coverage&lt;/a&gt; and put it into a separate component: &lt;a href=&quot;http://github.com/sebastianbergmann/php-code-coverage&quot;&gt;PHP_CodeCoverage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;PHP_CodeCoverage is a component that provides collection, processing, and rendering functionality for PHP code coverage information. It makes PHPUnit's mature code coverage functionality available outside of PHPUnit.&lt;/p&gt;

&lt;p&gt;Having all code that deals with code coverage in a separate component allows for easier development and better testing. The first result of these improved development conditions is a small new feature that I recently implemented, the support for the &lt;acronym title=&quot;Change Risk Analysis and Predictions&quot;&gt;CRAP&lt;/acronym&gt; metric.&lt;/p&gt;

&lt;p&gt;From &lt;a href=&quot;http://www.crap4j.org/&quot;&gt;crap4j.org&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The CRAP (Change Risk Analysis and Predictions) software metric [has] a mildly offensive metric name [and helps] to help protect you from truly offensive code.&lt;/p&gt;
&lt;p&gt;The CRAP metric combines &lt;a href=&quot;http://en.wikipedia.org/wiki/Cyclomatic_complexity&quot;&gt;cyclomatic complexity&lt;/a&gt; and code coverage from automated tests (e.g. [PHPUnit] tests) to help you identify code that might be particularly difficult to understand, test, or maintain &amp;mdash; the kind of code that makes developers say: &#8220;This is crap!&#8221; or, if they are stuck maintaining it, &#8220;Oh, crap!&#8221;.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The screenshot below shows how the CRAP metric is reported in the HTML code coverage report:&lt;/p&gt;

&lt;a href=&quot;http://sebastian-bergmann.de/uploads/crap.png&quot;&gt;&lt;img alt=&quot;Code Coverage Report&quot; border=&quot;0&quot; src=&quot;http://sebastian-bergmann.de/uploads/crap-highlight.png&quot; /&gt;&lt;/a&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit Development Moved to GitHub</title>
		<link href="http://sebastian-bergmann.de/archives/876-PHPUnit-Development-Moved-to-GitHub.html"/>
		<id>http://sebastian-bergmann.de/archives/876-guid.html</id>
		<updated>2009-12-26T10:45:00+00:00</updated>
		<content type="html">&lt;p&gt;Over the Christmas holidays I took a break from translating and editing the
&lt;a href=&quot;http://phpqabook.com/&quot;&gt;book on quality assurance in PHP projects&lt;/a&gt;
that I am working on to finally migrate the code repository of
&lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt; from a self-hosted
&lt;a href=&quot;http://subversion.tigris.org/&quot;&gt;Subversion&lt;/a&gt; repository to a
&lt;a href=&quot;http://git-scm.com/&quot;&gt;Git&lt;/a&gt; repository that is hosted on
&lt;a href=&quot;http://github.com/&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;How did I get here?&lt;/h3&gt;

&lt;p&gt;I was staying at &lt;a href=&quot;http://openquery.com/&quot;&gt;Arjen&lt;/a&gt;'s place in Brisbane
in August 2008 and one day we talked about distributed version control. Although I
knew the basic concepts behind it, I was not yet convinced enough to take the
plunge and try it out. Our discussion changed that, but it was not until my
second trip to Australia later that year that I took the initial code for
PHP_ObjectFreezer (which I had on my laptop since I started to hack on it
together with &lt;a href=&quot;http://www.priebsch.de/&quot;&gt;Stefan&lt;/a&gt; on the flight to
Atlanta for php|works 2008) and put it into a
&lt;a href=&quot;http://bazaar.canonical.com/en/&quot;&gt;bzr&lt;/a&gt; repository on
&lt;a href=&quot;http://launchpad.net/&quot;&gt;Launchpad&lt;/a&gt;. I grew comfortable enough with
bzr quickly, but never really warmed up to Launchpad.&lt;/p&gt;

&lt;p&gt;Around that time, I was hearing more and more positive things about Git and
GitHub from my peers. So I took the PHP_ObjectFreezer code base and migrated it
to Git and hosted the repository and GitHub to experiment with both the tool and
the platform. It was a step that I did not regret and all the projects that I
started since then are hosted on GitHub:
&lt;a href=&quot;http://github.com/sebastianbergmann/bytekit-cli&quot;&gt;bytekit-cli&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/phpcpd&quot;&gt;phpcpd&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/phpdcd&quot;&gt;phpdcd&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/phploc&quot;&gt;phploc&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/php-code-coverage&quot;&gt;PHP_CodeCoverage&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/php-file-iterator&quot;&gt;PHP_FileIterator&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/php-object-freezer&quot;&gt;PHP_ObjectFreezer&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/php-text-template&quot;&gt;Text_Template&lt;/a&gt;,
&lt;a href=&quot;http://github.com/sebastianbergmann/php-token-stream&quot;&gt;PHP_TokenStream&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Why did I do this?&lt;/h3&gt;

&lt;p&gt;Let me start with a quote from GitHub.com:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;&lt;li&gt;Git is a fast, efficient, distributed version control system ideal for the collaborative development of software.&lt;/li&gt;
&lt;li&gt;GitHub is the easiest (and prettiest) way to participate in that collaboration: fork projects, send pull requests, monitor development, all with ease.&lt;/li&gt;&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Over the last year, I have come to appreciate Git and GitHub a lot and also
wanted to use them for PHPUnit.&lt;/p&gt;&lt;p&gt;Sure, I could have used &lt;a href=&quot;http://www.kernel.org/pub/software/scm/git/docs/git-svn.html&quot;&gt;git-svn&lt;/a&gt;
for bi-directional operation between the existing Subversion repository and Git,
but this would have always felt like only going half the way.&lt;/p&gt;&lt;p&gt;The arguments in
favour of distributed version control systems are discussed by others far better
than I could discuss them here, so I will just quote Ian Clatworthy's
&lt;a href=&quot;http://ianclatworthy.files.wordpress.com/2007/10/dvcs-why-and-how3.pdf&quot;&gt;paper on distributed version control systems&lt;/a&gt;,
in which discusses not only the technical differences between traditional
version control systems and distributed version control systems, but also the
differences with regard to development workflows and developer interaction:&lt;/p&gt;
&lt;blockquote&gt;&lt;ul&gt;&lt;li&gt;Developers can collaborate directly without needing central
authority or incurring central administration overhead&lt;/li&gt;&lt;li&gt;Developers can
still be productive when the umbilical cord to their central VCS repository is
broken, e.g. when travelling.&lt;/li&gt;&lt;li&gt;Creating and destroying branches are
simple operations. This is particularly useful when experimenting with new
ideas, e.g. a &lt;i&gt;spike&lt;/i&gt; when using &lt;a href=&quot;http://en.wikipedia.org/wiki/Extreme_Programming&quot;&gt;eXtreme Programming&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Ad-hoc collaboration with peers [is facilitated by] intelligent merge
tracking [because] merging early and merging often is both possible and
surprisingly unpainful. It is difficult to explain just how much of an impact
this can make on how co-developers can work together more easily, e.g. when
&lt;a href=&quot;http://en.wikipedia.org/wiki/Pair_Programming&quot;&gt;Pair Programming&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;

&lt;h3&gt;What does this mean for you?&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://github.com/sebastianbergmann/phpunit&quot;&gt;PHPUnit is now hosted
on GitHub.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a nutshell, this means that the development of PHPUnit is now more open
than it was before. If you want to contribute, you just need to
&lt;a href=&quot;http://help.github.com/forking/&quot;&gt;fork&lt;/a&gt; PHPUnit on GitHub and create
a &lt;a href=&quot;http://progit.org/book/ch3-4.html&quot;&gt;topic branch&lt;/a&gt; for your
contribution. Then let me know about your topic branch and I may or may not
merge it.&lt;/p&gt;

&lt;p&gt;If you are currently using &lt;a href=&quot;http://svnbook.red-bean.com/en/1.5/svn.advanced.externals.html&quot;&gt;svn:externals&lt;/a&gt;
to pull PHPUnit into your own Subversion repository, you need to think about an
alternative as PHPUnit's Subversion repository is no longer updated and will
eventually go away.&lt;/p&gt;

&lt;h3&gt;How did I do it?&lt;/h3&gt;

&lt;p&gt;As this might be of interest to someone who wants to migrate his/her repository
from Subversion to Git, here is how I performed the migration.&lt;/p&gt;

&lt;p&gt;I started by creating a local mirror of the Subversion repository:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre&gt;# Fetch Subversion repository
svnadmin create phpunit.svn
 
cat 'EOF' &gt; phpunit.svn/hooks/pre-revprop-change
#!/bin/sh
USER=&quot;$3&quot;
 
if [ &quot;$USER&quot; = &quot;svnsync&quot; ]; then exit 0; fi
 
echo &quot;Only the svnsync user can change revprops&quot; &gt;&amp;amp;2
exit 1
EOF
 
chmod +x phpunit.svn/hooks/pre-revprop-change
 
svnsync init \
  --username svnsync \
  file://`pwd`/phpunit.svn \
  svn://svn.phpunit.de/phpunit
 
svnsync sync \
  --username svnsync \
  file://`pwd`/phpunit.svn&lt;/pre&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;Then I used &lt;a href=&quot;http://github.com/nirvdrum/svn2git&quot;&gt;svn2git&lt;/a&gt; for the
actual migration:&lt;/p&gt;
&lt;dl&gt;&lt;dd&gt;&lt;pre&gt;# Create directory for Git repository
mkdir phpunit.git &amp;amp;&amp;amp; cd phpunit.git
 
# Use svn2git to import repository
svn2git \
  --trunk trunk \
  --branches branches/release \
  --tags tags \
  --authors /home/sb/authors.txt \
  file:///home/sb/phpunit.svn/phpunit&lt;/pre&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;After that I had to delete quite a few superfluous branches and tags, but that
quickly dealt with. The final step was to create common ancestors for the &lt;tt&gt;master&lt;/tt&gt;, &lt;tt&gt;3.5&lt;/tt&gt;, and &lt;tt&gt;3.4&lt;/tt&gt; branches so that merging becomes easy and painless.&lt;/p&gt;

&lt;dl&gt;&lt;dd&gt;&lt;pre&gt;# Create 3.5 and 3.4 branches (in local repository)
git checkout remotes/origin/3.5 -b 3.5
git checkout remotes/origin/3.4 -b 3.4

# Create common ancestors for the master, 3.5, and 3.4 branches
git checkout 3.5 &amp;amp;&amp;amp; git merge --strategy=ours master
git checkout 3.4 &amp;amp;&amp;amp; git merge --strategy=ours 3.5

git checkout master &amp;amp;&amp;amp; git merge --strategy=ours 3.5
git checkout 3.5 &amp;amp;&amp;amp; git merge --strategy=ours 3.4&lt;/pre&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;After that I had to delete quite a few superfluous branches and tags, but that
quickly dealt with.&lt;/p&gt;

&lt;p&gt;At this point I would like to thank &lt;a href=&quot;http://blog.experimentalworks.net/&quot;&gt;David Soria Parra&lt;/a&gt;
who helped me figure out some details here and there.&lt;/p&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">phpUnderControl 0.5.0 released</title>
		<link href="http://www.manuel-pichler.de/archives/69-phpUnderControl-0.5.0-released.html"/>
		<id>http://www.manuel-pichler.de/archives/69-guid.html</id>
		<updated>2009-12-06T14:16:00+00:00</updated>
		<content type="html">&lt;p&gt;
  After quite some time of silence around &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2194&amp;entry_id=69&quot; title=&quot;http://php-under-control.org&quot;&gt;phpUnderControl&lt;/a&gt; I have bundled the 0.5.0 release today. Beside minor changes, bugfixes and enhancements this release contains one new major feature, the &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2182&amp;entry_id=69&quot; title=&quot;http://www.phpunit.de/browser/phpcb/trunk&quot;&gt;PHP_CodeBrowser&lt;/a&gt;.
&lt;/p&gt;

&lt;div class=&quot;serendipity_imageComment_center&quot;&gt;&lt;div class=&quot;serendipity_imageComment_img&quot;&gt;&lt;a class=&quot;serendipity_image_link&quot; href=&quot;http://www.manuel-pichler.de/uploads/phpUnderControl/php-under-contro-and-php-code-browser.png&quot;&gt;&lt;!-- s9ymdb:60 --&gt;&lt;img class=&quot;serendipity_image_center&quot; width=&quot;400&quot; src=&quot;http://www.manuel-pichler.de/uploads/phpUnderControl/php-under-contro-and-php-code-browser.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;serendipity_imageComment_txt&quot;&gt;phpUnderControl integrating PHP_CodeBrowser&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;
  The &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2182&amp;entry_id=69&quot; title=&quot;http://www.phpunit.de/browser/phpcb/trunk&quot;&gt;PHP_CodeBrowser&lt;/a&gt; is a separate application that collects various XML log files with different project metrics/violations and presents them in a browseable source view with syntax highligting. This tool is a contribution by the &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2184&amp;entry_id=69&quot; title=&quot;http://www.mayflower.de/&quot;&gt;Mayflower GmbH&lt;/a&gt;, where it was developed and now shared with the Open Source Community. At this point I would like to thank Mayflower as a whole and in particular at &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2185&amp;entry_id=69&quot; title=&quot;http://blog.thinkphp.de/archives/464-PHP_CodeBrowser-Release-version-0.1.0.html&quot;&gt;Elger&lt;/a&gt; and &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2186&amp;entry_id=69&quot; title=&quot;http://phpmyfaq.de/&quot;&gt;Thorsten&lt;/a&gt;, which were responsible for all technical aspects of this contribution.
&lt;/p&gt;

&lt;p&gt;
  To use the PHP_CodeBrowser you must add an additional &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2187&amp;entry_id=69&quot; title=&quot;http://cruisecontrol.sourceforge.net/main/configxml.html#execute&quot;&gt;execute publisher&lt;/a&gt; to your &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2188&amp;entry_id=69&quot; title=&quot;http://cruisecontrol.sourceforge.net&quot;&gt;CruiseControl&lt;/a&gt; &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2189&amp;entry_id=69&quot; title=&quot;http://cruisecontrol.sourceforge.net/main/configxml.html&quot;&gt;config.xml&lt;/a&gt; file that generates the PHP_CodeBrowser html report and an additional &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2190&amp;entry_id=69&quot; title=&quot;http://cruisecontrol.sourceforge.net/main/configxml.html#artifactspublisher&quot;&gt;artifacts publisher&lt;/a&gt; to move the generated PHP_CodeBrowser report into the projects artifacts directory. 
&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&amp;gt;
&amp;lt;cruisecontrol&amp;gt;
  &amp;lt;!-- ... --&amp;gt;
  &amp;lt;project name=&quot;PHP_Depend&quot; buildafterfailed=&quot;false&quot;&amp;gt;
    &amp;lt;!-- ... --&amp;gt;
    &amp;lt;publishers&amp;gt;
      &amp;lt;!-- ... --&amp;gt;
      &amp;lt;execute command=&quot;phpcb 
        --log projects/${project.name}/build/logs 
        --source projects/${project.name}/source/PHP 
        --output projects/${project.name}/build/php-code-browser&quot;/&amp;gt;
      &amp;lt;artifactspublisher 
        dir=&quot;projects/${project.name}/build/php-code-browser&quot; 
        dest=&quot;artifacts/${project.name}&quot; 
        subdirectory=&quot;php-code-browser&quot;/&amp;gt;
      &amp;lt;!-- ... --&amp;gt;
    &amp;lt;/publishers&amp;gt;
  &amp;lt;/project&amp;gt;
&amp;lt;/cruisecontrol&amp;gt;
&lt;/pre&gt;

&lt;p&gt;
  But why do we use a CruiseControl &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2191&amp;entry_id=69&quot; title=&quot;http://cruisecontrol.sourceforge.net/main/configxml.html#publishers&quot;&gt;publishers&lt;/a&gt; instead of a regular ant &lt;em&gt;(Your build tool here)&lt;/em&gt; &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2192&amp;entry_id=69&quot; title=&quot;http://ant.apache.org/manual/using.html#targets&quot;&gt;target&lt;/a&gt;? The answer is really simple. The PHP_CodeBrowser must be the very last artifact generated for a project, which means it must also run after PHPUnit, to collect the test result logs. But in most setups PHPUnit is configured with &lt;code&gt;failonerror=&quot;on&quot;&lt;/code&gt; to mark a build as failed, when an error occured during the test execution. But with this configuration a following PHP_CodeBrowser target would never be executed by &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2193&amp;entry_id=69&quot; title=&quot;http://ant.apache.org/&quot;&gt;ant&lt;/a&gt;, because the build failed already. This cannot happen with a CruiseControl publisher which is always executed in a separated process.
&lt;/p&gt;

&lt;p&gt;
  If you create a new project with phpUnderControl's &lt;code&gt;project&lt;/code&gt; command, phpUnderControl will automatically search for an installed PHP_CodeBrowser and add the required publishers to your &lt;code&gt;config.xml&lt;/code&gt; file when it is present.
&lt;/p&gt;

&lt;pre&gt;
mapi@arwen ~ $ phpuc project \
       --project-name PHP_Depend \
       --source-dir PHP \
       --test-case PHP_Depend_AllTests \
       --test-dir tests \
       --test-file PHP/Depend/AllTests.php \
       --version-control svn \
       --version-control-url http://svn.pdepend.org/branches/0.9.0 \
       /opt/cruisecontrol/cruisecontrol-bin-2.8.2
&lt;/pre&gt;

&lt;p&gt;
  To get the latest version of phpUnderControl, you can use the PEAR-Channel-Server:
&lt;/p&gt;

&lt;pre&gt;
mapi@arwen ~ $ pear channel-discover pear.phpunit.de
mapi@arwen ~ $ pear install phpunit/phpUnderControl-beta
&lt;/pre&gt;

&lt;p&gt;
  or you can check it out from the subversion repository:
&lt;/p&gt;

&lt;pre&gt;
mapi@arwen ~ $ svn co svn://phpunit.de/phpunit/phpUnderControl/trunk
&lt;/pre&gt;</content>
		<author>
			<name>Manuel Pichler</name>
			<email>nospam@example.com</email>
			<uri>http://www.manuel-pichler.de/</uri>
		</author>
		<source>
			<title type="html">Manuel Pichler - phpundercontrol</title>
			<subtitle type="html">Trust is good, (phpUnder)Control is better.</subtitle>
			<link rel="self" href="http://manuel-pichler.de/feeds/categories/10-phpundercontrol.rss"/>
			<id>http://manuel-pichler.de/feeds/categories/10-phpundercontrol.rss</id>
			<updated>2010-02-01T05:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Update</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/16-Update.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/16-guid.html</id>
		<updated>2009-11-04T08:30:00+00:00</updated>
		<content type="html">It has been quiet on this website since we posted the last contributed chapter abstract in June and it is time to give you an update. But first, allow me to refresh your memory on the list of contributed chapters:&lt;blockquote&gt;&lt;ul&gt;&lt;li&gt;Best Practices&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://qualityassuranceinphpprojects.com/archives/10-TYPO3-The-Agile-Future-of-a-Ponderous-Project.html&quot;&gt;TYPO3: The Agile Future of a Ponderous Project&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://qualityassuranceinphpprojects.com/archives/15-Unit-Testing-Bad-Practices-by-Example.html&quot;&gt;Unit Testing Bad Practices by Example&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://qualityassuranceinphpprojects.com/archives/7-Quality-Assurance-at-Digg-Inc..html&quot;&gt;Quality Assurance at Digg&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Servers and Services&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://qualityassuranceinphpprojects.com/archives/14-Testing-Service-Oriented-APIs.html&quot;&gt;Testing Service Oriented APIs&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://qualityassuranceinphpprojects.com/archives/4-Testing-a-WebDAV-Server.html&quot;&gt;Testing a WebDAV Server&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://qualityassuranceinphpprojects.com/archives/5-Testing-Database-Interaction.html&quot;&gt;Testing Database Interaction&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Architecture&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://qualityassuranceinphpprojects.com/archives/11-Testing-Symfony-and-Symfony-Applications.html&quot;&gt;Testing Symfony and Symfony Applications&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://qualityassuranceinphpprojects.com/archives/8-Testing-the-ezcGraph-Component.html&quot;&gt;Testing the ezcGraph Component&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;QA in the Large&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://qualityassuranceinphpprojects.com/archives/6-Large-Scale-Selenium-Based-Testing.html&quot;&gt;Large-Scale Selenium-Based Testing at studiVZ&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://qualityassuranceinphpprojects.com/archives/13-Continuous-Integration-with-phpUnderControl.html&quot;&gt;Continuous Integration with phpUnderControl&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://qualityassuranceinphpprojects.com/archives/3-swoodoo-A-True-Agile-Story.html&quot;&gt;swoodoo: A True Agile Story&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Non-Functional Aspects&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://qualityassuranceinphpprojects.com/archives/2-Performance-Testing.html&quot;&gt;Performance&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Usability&lt;/li&gt;&lt;li&gt;Security&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;As we only have a deadline for the German edition so far and since we received the majority of contributed chapters in English, Stefan and I are currently busy translating the contributed chapters from English to German in an effort to meet our deadline. We are currently looking at a release date for the German edition in late spring / early summer of 2010.&lt;br /&gt;
&lt;br /&gt;
Once we have finished the manuscript for the German edition, we will start working on the manuscript for the English edition. Hopefully, this process will be much faster as we only need to translate a couple of chapters from German to English. We are hopeful that the English edition will be available not much later than the German edition.</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit 3.4.2</title>
		<link href="http://sebastian-bergmann.de/archives/875-PHPUnit-3.4.2.html"/>
		<id>http://sebastian-bergmann.de/archives/875-guid.html</id>
		<updated>2009-10-25T14:55:00+00:00</updated>
		<content type="html">&lt;p&gt;I have released &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit 3.4.2&lt;/a&gt; today.&lt;/p&gt;&lt;p&gt;Besides the usual bug fixes, this release disables the backup and restore operations for static attributes (that was introduced in PHPUnit 3.4.0) by default.&lt;/p&gt;&lt;p&gt;The previous default setting caused too many problems with existing test suites (problems that would have been recognized earlier had users actually tested the PHPUnit 3.4 release candidates).&lt;/p&gt;&lt;p&gt;To enable the backup and restore operations for static attributes, simply pass the &lt;code&gt;--static-backup&lt;/code&gt; command-line switch, use the &lt;a href=&quot;http://www.phpunit.de/manual/current/en/appendixes.annotations.html#appendixes.annotations.backupStaticAttributes&quot;&gt;&lt;code&gt;@backupStaticAttributes&lt;/code&gt;&lt;/a&gt; annotation, or the &lt;a href=&quot;http://www.phpunit.de/manual/current/en/appendixes.configuration.html#appendixes.configuration.phpunit&quot;&gt;XML configuration file&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Below is the full list of changes:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/889&quot; title=&quot;enhancement: --skeleton-class flag doesn't work with @depends annotation (closed: fixed)&quot;&gt;#889&lt;/a&gt;: &lt;tt&gt;--skeleton-class&lt;/tt&gt; does not work with &lt;tt&gt;@depends&lt;/tt&gt; annotation. &lt;a href=&quot;http://www.phpunit.de/changeset/5270&quot; title=&quot;- Merge [5263:5265] and [5269].&quot;&gt;[5270]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/902&quot; title=&quot;defect: --log-metrics throws Exception on namespaced code (closed: fixed)&quot;&gt;#902&lt;/a&gt;: &lt;tt&gt;PHPUnit_Util_File::getClassesInFile()&lt;/tt&gt; does not handle nested namespaces correctly. &lt;a href=&quot;http://www.phpunit.de/changeset/5272&quot; title=&quot;- Merge [5271].&quot;&gt;[5272]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/905&quot; title=&quot;defect: Files with no methods or classes show incorrect code coverage with ... (closed: fixed)&quot;&gt;#905&lt;/a&gt;: Files with no methods or classes show incorrect code coverage with &lt;tt&gt;--coverage-clover&lt;/tt&gt;. &lt;a href=&quot;http://www.phpunit.de/changeset/5276&quot; title=&quot;- Merge [5275].&quot;&gt;[5276]&lt;/a&gt; &lt;a href=&quot;http://www.phpunit.de/changeset/5284&quot; title=&quot;- Merge [5283].&quot;&gt;[5284]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/909&quot; title=&quot;defect: Stubbing a web service with getMockFromWsdl throws a fatal error. (closed: fixed)&quot;&gt;#909&lt;/a&gt;: Stubbing a web service with &lt;tt&gt;getMockFromWsdl()&lt;/tt&gt; throws a fatal error. &lt;a href=&quot;http://www.phpunit.de/changeset/5281&quot; title=&quot;- Merge [5280].&quot;&gt;[5281]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/918&quot; title=&quot;defect: Truncate operation throws an error (closed: fixed)&quot;&gt;#918&lt;/a&gt;: Truncate operation throws an error. &lt;a href=&quot;http://www.phpunit.de/changeset/5286&quot; title=&quot;- Merge [5285].&quot;&gt;[5286]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;The backup and restore operations for static attributes has been disabled by default. &lt;a href=&quot;http://www.phpunit.de/changeset/5288&quot; title=&quot;- Partially merge [5287].&quot;&gt;[5288]&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Upcoming talks&#8230;</title>
		<link href="http://www.frontalaufprall.com/2009/09/25/upcoming-talks-2/"/>
		<id>http://www.frontalaufprall.com/?p=181</id>
		<updated>2009-09-25T14:29:21+00:00</updated>
		<content type="html">&lt;p&gt;After my &lt;a href=&quot;http://phpterror.wordpress.com/2009/08/26/oxid-esales-the-extend-parade/&quot; target=&quot;_blank&quot;&gt;discussion with Arno&lt;/a&gt; about the right way to develop software I&amp;#8217;ve decided that it would be a good chance to meet him in person while visiting &lt;a href=&quot;http://phpconference.es/&quot; target=&quot;_blank&quot;&gt;PHP Con in Barcelona&lt;/a&gt;. And besides that, Barcelona and the PHP Folks there is always good for a visit.&lt;/p&gt;
&lt;p&gt;Therefore there is - once again - another chance to enjoy my talks called &amp;#8216;Refactor it! A practical journey into the test-driven world&amp;#8217; and &amp;#8216;Agile Development with PHP in Practice&amp;#8217; . I did run both topics already quite often but obviously there is still a need for it. If you are new to agile development or interested in refactoring your old (shitty?) sourcecode - come in and join.&lt;/p&gt;
&lt;p&gt;And if you are interested in the&lt;a href=&quot;http://www.frontalaufprall.com/2009/08/27/extension-terror/&quot; target=&quot;_blank&quot;&gt; topic of the discussion with Arno&lt;/a&gt; - feel free to contact me. I will organize a meeting with where we will discuss the whole item over a few bottles of red wine. After receiving so many comments it would be nice if we get a few more opinions together.&lt;/p&gt;
&lt;p&gt;After Barcelona Summer is definitly gone and it&amp;#8217;s - as every year - time for the &lt;a href=&quot;http://it-republik.de/php/phpconference09/&quot; target=&quot;_blank&quot;&gt;international PHP Conference&lt;/a&gt; in Karlsruhe. This time &lt;a href=&quot;http://phpmyfaq.de/&quot; target=&quot;_blank&quot;&gt;Thorsten&lt;/a&gt; and me will run a half-day Workshop called &amp;#8220;Unittest for Dummies&amp;#8221; which will address unit testing beginners. If you are not already into TDD you should definitly consider to come. Furthermore there will be a session about how &lt;a href=&quot;http://www.swoodoo.com/de&quot; target=&quot;_blank&quot;&gt;swoodoo&lt;/a&gt; managed to withstand the massive amount of requests due to (*yeah*&amp;#8230;) the big success. I&amp;#8217;ve titled it &amp;#8220;caching, sharding, distributing - Scaling best practices&amp;#8221; - so you might get an idea about the contents.&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s it - live from the &amp;#8220;Oktoberfest&amp;#8221; in munich &lt;img src=&quot;http://www.frontalaufprall.com/wp-includes/images/smilies/icon_wink.gif&quot; alt=&quot;;)&quot; class=&quot;wp-smiley&quot; /&gt; &lt;/p&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<uri>http://www.frontalaufprall.com</uri>
		</author>
		<source>
			<title type="html">Frontalaufprall &#187; PHP related</title>
			<subtitle type="html">PHP, Agile Development und vorallem auch dies und das</subtitle>
			<link rel="self" href="http://www.frontalaufprall.com/category/php/feed/"/>
			<id>http://www.frontalaufprall.com/category/php/feed/</id>
			<updated>2010-03-15T00:00:23+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit 3.4.0</title>
		<link href="http://sebastian-bergmann.de/archives/873-PHPUnit-3.4.0.html"/>
		<id>http://sebastian-bergmann.de/archives/873-guid.html</id>
		<updated>2009-09-16T15:55:00+00:00</updated>
		<content type="html">&lt;p&gt;A year and a day has passed since the release of PHPUnit 3.3. Time to finally release &lt;a href=&quot;http://www.phpunit.de/wiki/ChangeLog34&quot;&gt;PHPUnit 3.4&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Among the features introduced in this new version, the most notable are the support for &lt;a href=&quot;http://sebastian-bergmann.de/archives/826-Test-Dependencies-in-PHPUnit-3.4.html&quot;&gt;test dependencies&lt;/a&gt; and &lt;a href=&quot;http://sebastian-bergmann.de/archives/848-Fixture-Reuse-in-PHPUnit-3.4.html&quot;&gt;fixture reuse&lt;/a&gt; as well as the possibility to run tests in separate PHP processes for increased test isolation. Please have a look at the &lt;a href=&quot;http://www.phpunit.de/wiki/ChangeLog34&quot;&gt;ChangeLog&lt;/a&gt; for a complete list of changes.&lt;/p&gt;&lt;p&gt;Work on PHPUnit 3.5 has already started: the &lt;a href=&quot;http://github.com/sebastianbergmann/php-code-coverage&quot;&gt;php-code-coverage&lt;/a&gt; project on GitHub is home to a refactoring of PHPUnit's code coverage functionality that will be one of the &quot;hallmark features&quot; of PHPUnit 3.5. It will also make PHPUnit's code coverage functionality available outside the scope of PHPUnit.&lt;/p&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Extension Terror?</title>
		<link href="http://www.frontalaufprall.com/2009/08/27/extension-terror/"/>
		<id>http://www.frontalaufprall.com/?p=173</id>
		<updated>2009-08-27T11:48:59+00:00</updated>
		<content type="html">&lt;p&gt;When I first saw the posting about &amp;#8216;bad&amp;#8217; code in &lt;a href=&quot;http://www.oxid-esales.com/en/download/open-source-ecommerce-solution-oxid-eshop-community-edition&quot; target=&quot;_blank&quot;&gt;OXID&lt;/a&gt; over at &lt;a href=&quot;http://phpterror.wordpress.com/2009/08/26/oxid-esales-the-extend-parade/&quot; target=&quot;_blank&quot;&gt;phpterror&lt;/a&gt; I wondered if I could ignore this - but now I&amp;#8217;ve realized that this article was published on Planet-PHP and even more - other people start to &lt;a href=&quot;http://phpkitchen.com/2009/08/phpterror-on-oxid-eshop/&quot; target=&quot;_blank&quot;&gt;copy the content&lt;/a&gt; of the article.&lt;/p&gt;
&lt;p&gt;As I am the guy who introduced the disliked functionality many years ago ( actually years before ZF popped up) I feel the need for a statement to put the things into the right order. Please note that I did work for OXID in the past (years ago) but I do not nowadays.&lt;/p&gt;
&lt;p&gt;Arno criticised the way modules == classes are instantiated in OXID eShop. Actually I do believe that exactly this feature is the most coolest in OXID and should be implemented in more OSS.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Let&amp;#8217;s start with the &amp;#8220;why the fuck did the guy implement this&amp;#8221;?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you do run a website out there you know how important it is to keep it up-to-date with the latest patches due to security reasons. Now imagine - we are in eCommerce area. You deal with payments, credit card data and sensitive information about what people ordered from your shop. Not only Creditcard data is sensitive - imagine it would leak that you ordered the extra-big-boobs doll? You see - especially in this area you need to make absolutly sure that your servers and the software is safe.&lt;/p&gt;
&lt;p&gt;Unfortunately you can&amp;#8217;t start an eCommerce business out-of-the-box. You need to adopt the software to your needs and processes. Think of payment, ERP, delivery notifications, link to your stock, uploads to price-comparison sites etc. Some of the functionality you might need to develop yourself - for other stuff you might find already existing modules out there.&lt;/p&gt;
&lt;p&gt;Therefore you need to change code, and/or install external modules which modify the functionality. In former days you simply edited the source code (as we are talking about OSS) and made manually sure that the modules you install are compatible. Don&amp;#8217;t forget - each of them will work with the out-of-the-box shop - but they still should work after you added your changes and - also need to work after you installed some other external modules which might overwrite/change the same classes/functionality which your new module also want to change.&lt;/p&gt;
&lt;p&gt;You end up with a highly customized shop, many changes, a lot of work to dig through the sourcecode of the installed modules to make sure that they don&amp;#8217;t harm themself and&amp;#8230; you lost the possibility to automatically appply patches/releases. Upon each patch or new release you need to manually redo/check your changes.&lt;/p&gt;
&lt;p&gt;This sucks. It sucks a lot. And this is exactly why I&amp;#8217;ve introduced the criticised module functionality.&lt;br /&gt;
&lt;strong&gt;&lt;br /&gt;
So what did I do?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As &lt;a href=&quot;http://phpterror.wordpress.com/2009/08/26/oxid-esales-the-extend-parade/&quot; target=&quot;_blank&quot;&gt;Arno&lt;/a&gt; already copy&amp;amp;pasted the source I won&amp;#8217;t repeat it here. But let me explain the main idea behind the concept.&lt;/p&gt;
&lt;p&gt;As OXID is fully OOP you can change all the functionality by inheriting your class from any base class you might want to change. You add your changes and - et voila - you still can overwrite the bases classes with new releases/patches and your changes will work. This is called object oriented programming.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s assume you want to change the method &amp;#8220;getPrice&amp;#8221; in the class &amp;#8220;oxarticle&amp;#8221;. You simply overwrite oxArticle::getPrice and&amp;#8230; it would work if the system would know that your class exists. Therefore you need to register your class and let the OXID Framework know about it so that it automatically will instantiate your class instead of oxArticle each time the object is needed.&lt;/p&gt;
&lt;p&gt;So far, so good, so what?&lt;/p&gt;
&lt;p&gt;What happens if you install some other module ( e.g. from &lt;a href=&quot;http://www.oxid-esales.com/en/exchange&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;) which will change the same method in same class? It would screw your changes and you would end up with manual changes again. To avoid this, the OXID Framework supports &amp;#8220;chaining&amp;#8221; of inheritance&amp;#8230; and the order is set in the config. So you can define that the modules oxArticle implementation is executed before your class or after.&lt;/p&gt;
&lt;p&gt;I do believe that by overriding the classes you do get the most flexible option to change everything without loosing the functionality to update the shop whenever you want. For sure this could be solved differently. Events or Hooks would have been a way to go - but this would involve a lot of additional coding == lines of code and therefore introduce new vectors for bugs. And - it is by far not as flexible as overriding the class. Nowadays it could be solved also with Reflection. But this is a bit too &amp;#8220;magic&amp;#8221; in my opinion. Therefore I still believe that the way I&amp;#8217;ve chosen is the best way to solve the problem and - most likely - I would do it again today.&lt;/p&gt;
&lt;p&gt;Last but not least - I would like to comment the &lt;a href=&quot;http://phpterror.wordpress.com/2009/08/26/oxid-esales-show-me-your-94-unit-test-coverage/&quot; target=&quot;_blank&quot;&gt;show me your 94% Unit Test&#160;coverage!&lt;/a&gt; posting.&#160; I&amp;#8217;ve contacted OXID already one year ago about this and I fully agree with Arno here. It sucks to advertise with some test-driven-development features and then keep the tests for yourself. OXID has to change this. Now.&lt;/p&gt;
&lt;p&gt;Today I had a good skype discussion about the issue with Arno - I really like his style even though we both do not agree &lt;img src=&quot;http://www.frontalaufprall.com/wp-includes/images/smilies/icon_wink.gif&quot; alt=&quot;;)&quot; class=&quot;wp-smiley&quot; /&gt; - and the result for me was that&#160; I&amp;#8217;ve decided to submit a few proposals to the &lt;a href=&quot;http://phpconference.es/&quot; target=&quot;_blank&quot;&gt;PHP Conference in Barcelona&lt;/a&gt; to get the chance to meet Arno and discuss the whole issue over a bottle of spanish Rioja. Or two. Or&amp;#8230;&lt;/p&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<uri>http://www.frontalaufprall.com</uri>
		</author>
		<source>
			<title type="html">Frontalaufprall &#187; PHP related</title>
			<subtitle type="html">PHP, Agile Development und vorallem auch dies und das</subtitle>
			<link rel="self" href="http://www.frontalaufprall.com/category/php/feed/"/>
			<id>http://www.frontalaufprall.com/category/php/feed/</id>
			<updated>2010-03-15T00:00:23+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit 3.4.0RC1</title>
		<link href="http://sebastian-bergmann.de/archives/872-PHPUnit-3.4.0RC1.html"/>
		<id>http://sebastian-bergmann.de/archives/872-guid.html</id>
		<updated>2009-08-18T10:30:00+00:00</updated>
		<content type="html">&lt;p&gt;The first release candidate of &lt;a href=&quot;http://www.phpunit.de/wiki/ChangeLog34&quot;&gt;PHPUnit 3.4&lt;/a&gt; is now available.&lt;/p&gt;

&lt;p&gt;Among the many new features introduced in this new version, the most notable are the support for &lt;a href=&quot;http://sebastian-bergmann.de/archives/826-Test-Dependencies-in-PHPUnit-3.4.html&quot;&gt;test dependencies&lt;/a&gt; and &lt;a href=&quot;http://sebastian-bergmann.de/archives/848-Fixture-Reuse-in-PHPUnit-3.4.html&quot;&gt;fixture reuse&lt;/a&gt; as well as the possibility to run tests in separate PHP processes for increased test isolation. Please have a look at the &lt;a href=&quot;http://www.phpunit.de/wiki/ChangeLog34&quot;&gt;ChangeLog&lt;/a&gt; for a complete list of changes.&lt;/p&gt;

&lt;p&gt;You can help make PHPUnit 3.4 a &quot;good release&quot; by running your test suites with it and report any problems or regressions that you may encounter. You help is much appreciated!&lt;/p&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHP 5.3 Release Party</title>
		<link href="http://www.priebsch.de/2009/07/php-53-release-party/"/>
		<id>http://www.priebsch.de/?p=386</id>
		<updated>2009-07-08T06:13:15+00:00</updated>
		<content type="html">PHP 5.3 BBQ Release Party M&#252;nchen

Wir w&#252;rden dich gerne zu der PHP 5.3 Release Party einladen, bei der das PHP 5.3 Release in M&#252;nchen gefeiert werden soll. Der Event findet am Freitag, den 17.07.2009 in M&#252;nchen statt. Die Release Party bietet auch die M&#246;glichkeit zu einem lockeren Treffen mit anderen &amp;#8220;PHP-Begeisterten&amp;#8221;. Nat&#252;rlich bist du auch [...]</content>
		<author>
			<name>Stefan Priebsch</name>
			<uri>http://www.priebsch.de</uri>
		</author>
		<source>
			<title type="html">Wahrnehmungen aus zwei Welten &#187; PHPUnit</title>
			<subtitle type="html">&lt;div id=&quot;wrapper&quot;&gt;
	&lt;div id=&quot;header&quot;&gt;
		&lt;span id=&quot;nav&quot;&gt;
		    &lt;a href=&quot;http://www.priebsch.de/&quot; title=&quot;Home&quot;&gt;Home&lt;/a&gt;&#160;&#160;|&#160;&#160;
			&lt;a href=&quot;http://www.priebsch.de/about&quot; title=&quot;&#220;ber&quot;&gt;&#220;ber&lt;/a&gt;&#160;&#160;|&#160;&#160;
			&lt;a href=&quot;http://www.priebsch.de/blog&quot; title=&quot;Blog&quot;&gt;Blog&lt;/a&gt;&#160;&#160;|&#160;&#160;
			&lt;a href=&quot;http://www.priebsch.de/thePHP.cc&quot; title=&quot;thePHP.cc&quot;&gt;thePHP.cc&lt;/a&gt;
        &lt;/span&gt;
            
        &lt;span&gt;
            &lt;p&gt;&lt;a href=&quot;http://www.priebsch.de/en/&quot; title=&quot;This page in English&quot;&gt;&lt;img src=&quot;http://www.priebsch.de/assets/images/en.gif&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
        &lt;/span&gt;
        
	&lt;/div&gt;

&lt;div class=&quot;generic fiveeighty noborder break&quot;&gt;
&lt;h1&gt;Goodbye Wordpress. Again, you have failed me.&lt;/h1&gt;&lt;p&gt;Ver&#246;ffentlicht am 10. Januar 2010&lt;/p&gt;
&lt;p&gt;View this post in German: &lt;a href=&quot;http://www.priebsch.de/blog/auf-wiedersehen-wordpress&quot;&gt;Auf Wiedersehen, Wordpress!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is not always a good idea to listen to others. But it is probably a good
idea to listen to yourself. I have had to learn that the hard way.
Last year, I have done quite some Code Review session together with Arne Blankerts and
Sebastian Bergmann at various IT conferences, where we showed 
 &amp;quot;Better not do this&amp;quot;-type 
&lt;a href=&quot;http://www.slideshare.net/sebastian_bergmann/php-code-review-1464932&quot;&gt;code examples&lt;/a&gt;
taken from popular open source PHP projects.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://wordpress.org&quot;&gt;Wordpress&lt;/a&gt; was not missing from these 
examples, after all Wordpress supposedly has a CRAP index of 
&lt;a href=&quot;http://jacobsantos.com/2007/general/what-is-your-crap-index/&quot;&gt;598398&lt;/a&gt;
and is known to have &lt;a href=&quot;http://wordpress.org/development/2009/08/2-8-4-security-release/&quot;&gt;security issues&lt;/a&gt;
time and again. Unfortunately, though I knew that Wordpress is one of those
PHP-based open source applications that you should better not use, I was running
my own blog on Wordpress.&lt;/p&gt;

&lt;p&gt;So it happened: last week I was incidentally looking at the source code
of my latest blog post. To my big surprise, I saw a &amp;lt;div&amp;gt; absolutely
positioned out of the viewable area, containing quite some links to 
&amp;quot;pharmaceutical&amp;quot; web sites. Needless to say that I had not put that
&amp;lt;div&amp;gt; into my blog post, but some hacker or exploit did.&lt;/p&gt;

&lt;p&gt;So it happened: just like a couple of years back, when that frequently used
PHP forum software had to go, after one of my servers had been hacked due to
a security issue in that very forum software, Wordpress is now gone forever
from my server. Goodbye, and thanks for nothing.&lt;/p&gt;
&lt;p&gt;Tags: &lt;a href=&quot;http://www.priebsch.de/tags/wordpress&quot;&gt;Wordpress&lt;/a&gt;, &lt;a href=&quot;http://www.priebsch.de/tags/relaunch&quot;&gt;Relaunch&lt;/a&gt;, &lt;a href=&quot;http://www.priebsch.de/tags/blog&quot;&gt;Blog&lt;/a&gt;, &lt;a href=&quot;http://www.priebsch.de/tags/php&quot;&gt;PHP&lt;/a&gt;, &lt;a href=&quot;http://www.priebsch.de/tags/crap&quot;&gt;CRAP&lt;/a&gt;, &lt;a href=&quot;http://www.priebsch.de/tags/hack&quot;&gt;hack&lt;/a&gt;, &lt;a href=&quot;http://www.priebsch.de/tags/fail&quot;&gt;fail&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;Kommentare?&lt;/h2&gt;&lt;p&gt;Wegen unverh&#228;ltnism&#228;&#223;ig viel Spam akzeptieren wir zur Zeit Kommentare &lt;a href=&quot;http://mailhide.recaptcha.net/d?k=016x3YaFhRW8g_-xAFUf6CTA==&amp;c=y75QkSt8ogDg6yNmnahz91eilMNLla0_tOTV5S-tTiQ=&quot; title=&quot;Klicken, um einen Kommentar zu hinterlassen&quot;&gt;nur per E-Mail&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;

&lt;div class=&quot;generic threeforty noborder end&quot;&gt;
&lt;h1&gt;Stefan Priebsch&lt;/h1&gt;
&lt;img src=&quot;http://www.priebsch.de/assets/images/stefan-priebsch.jpg&quot; alt=&quot;Stefan Priebsch&quot; class=&quot;left-img&quot; /&gt;
&lt;p&gt;Diplom-Informatiker Stefan Priebsch ist IT-Consultant, Trainer und Spezialist f&#252;r die Entwicklung PHP-basierter Software.&lt;/p&gt;
&lt;p&gt;Er ist Autor zahlreicher B&#252;cher und Fachartikel &#252;ber verschiedene Aspekte des Software-Lebenszyklus und spricht regelm&#228;&#223;ig auf internationalen IT-Konferenzen.&lt;/p&gt;
&lt;p&gt;Stefan Priebsch ist verheiratet und lebt und arbeitet in Wolfratshausen bei M&#252;nchen. Er ist Mitgr&#252;nder und Principal Consultant von thePHP.cc.&lt;/p&gt;&lt;/div&gt;

&lt;div class=&quot;generic threeforty&quot;&gt;
	&lt;h2&gt;Blog&lt;/h2&gt;&lt;h3&gt;&lt;a href=&quot;http://www.priebsch.de/blog/auf-wiedersehen-wordpress&quot;&gt;Auf Wiedersehen, Wordpress!&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;
Es ist nicht immer klug, auf andere zu h&#246;ren. Aber auf sich selbst sollte man
eigentlich schon h&#246;ren. Das habe ich jetzt auch wieder lernen m&#252;ssen.
 (vor 3 Tagen)&lt;br /&gt;&#187;&#160;&lt;a href=&quot;http://www.priebsch.de/blog/auf-wiedersehen-wordpress&quot;&gt;Blog-Eintrag lesen&lt;/a&gt;&lt;/p&gt;&lt;h3&gt;&lt;a href=&quot;http://www.priebsch.de/blog/wie-kann-ich-meinen-account-l&#246;schen&quot;&gt;Wie kann ich meinen Account l&#246;schen?&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;
Einen Account anlegen ist nicht schwer, ihn loszuwerden dagegen sehr. Ich fragte
den Support von sedo, wie ich meinen Account dort l&#246;schen kann.
 (vor 5 Tagen)&lt;br /&gt;&#187;&#160;&lt;a href=&quot;http://www.priebsch.de/blog/wie-kann-ich-meinen-account-l&#246;schen&quot;&gt;Blog-Eintrag lesen&lt;/a&gt;&lt;/p&gt;&lt;h3&gt;&lt;a href=&quot;http://www.priebsch.de/blog/codeworks09-feedback&quot;&gt;CodeWorks Feedback&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;
I would like to thank everybody who took the time and has provided me with
their feedback on my OOP and Design Patterns workshop at CodeWorks.
 (vor 97 Tagen)&lt;br /&gt;&#187;&#160;&lt;a href=&quot;http://www.priebsch.de/blog/codeworks09-feedback&quot;&gt;Blog-Eintrag lesen&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;

&lt;div class=&quot;generic twotwenty&quot;&gt;
	&lt;div&gt;&lt;p&gt;&lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/mta&quot;&gt;MTA&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/mvc&quot;&gt;MVC&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/wordpress&quot;&gt;Wordpress&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/qabook&quot;&gt;QABook&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/migration&quot;&gt;Migration&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/tek09&quot;&gt;tek09&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/unconference&quot;&gt;Unconference&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/php5.3&quot;&gt;PHP5.3&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/php&quot;&gt;PHP&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/codeworks09&quot;&gt;CodeWorks09&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/slides&quot;&gt;Slides&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/oop&quot;&gt;OOP&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/lifecycle&quot;&gt;Lifecycle&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/canada&quot;&gt;Canada&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/crap&quot;&gt;CRAP&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/selenium&quot;&gt;Selenium&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/starbucks&quot;&gt;Starbucks&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/workshop&quot;&gt;Workshop&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/conference&quot;&gt;Conference&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/atlanta&quot;&gt;Atlanta&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/testing&quot;&gt;Testing&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/blog&quot;&gt;Blog&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/arneblankerts&quot;&gt;ArneBlankerts&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/presentation&quot;&gt;Presentation&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/webcast&quot;&gt;Webcast&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/relaunch&quot;&gt;Relaunch&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/feedback&quot;&gt;Feedback&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/montreal&quot;&gt;Montreal&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/slideshare&quot;&gt;Slideshare&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/hack&quot;&gt;hack&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/chicago&quot;&gt;Chicago&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/training&quot;&gt;Training&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/phpquebec09&quot;&gt;PHPQuebec09&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/magento&quot;&gt;Magento&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/fail&quot;&gt;fail&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/u.s.a.&quot;&gt;U.S.A.&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/book&quot;&gt;Book&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/derickrethans&quot;&gt;DerickRethans&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/thephp.cc&quot;&gt;thePHP.cc&lt;/a&gt;&lt;/span&gt; &lt;span&gt;&lt;a href=&quot;http://www.priebsch.de/tags/sebastianbergmann&quot;&gt;SebastianBergmann&lt;/a&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;generic threeforty end&quot;&gt;
	&lt;h2&gt;Twitter&lt;/h2&gt;
	&lt;p&gt;spriebsch
  
@&lt;a href=&quot;http://twitter.com/nateabele&quot;&gt;nateabele&lt;/a&gt; achieving code coverage without assertions is a lie, because it does *not* tell that the code actually works (vor 13 Stunden)&lt;br /&gt;&#187;&#160;&lt;a href=&quot;http://twitter.com/spriebsch/statuses/7667214351&quot;&gt;Tweet lesen&lt;/a&gt;&lt;/p&gt;&lt;p&gt;RT @&lt;a href=&quot;http://twitter.com/thePHPcc&quot;&gt;thePHPcc&lt;/a&gt;: @&lt;a href=&quot;http://twitter.com/s_bergmann&quot;&gt;s_bergmann&lt;/a&gt;, @&lt;a href=&quot;http://twitter.com/arneblankerts&quot;&gt;arneblankerts&lt;/a&gt; and @&lt;a href=&quot;http://twitter.com/spriebsch&quot;&gt;spriebsch&lt;/a&gt; offer &amp;quot;Advanced PHP Training&amp;quot; in Montr&#233;al (&lt;a href=&quot;http://confoo.ca/en/training) just b ...&quot;&gt;http://confoo.ca/en/training) just b ...&lt;/a&gt; (vor einem Tag)&lt;br /&gt;&#187;&#160;&lt;a href=&quot;http://twitter.com/spriebsch/statuses/7632080902&quot;&gt;Tweet lesen&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I asked sedo support by email: &amp;quot;How can I delete my account?&amp;quot;. Answer: &amp;quot;We respect your privacy and will delete it right away&amp;quot; #epic #fail (vor 4 Tagen)&lt;br /&gt;&#187;&#160;&lt;a href=&quot;http://twitter.com/spriebsch/statuses/7518540490&quot;&gt;Tweet lesen&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&#187;&#160;&lt;a href=&quot;http://twitter.com/spriebsch&quot;&gt;Auf Twitter folgen&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;generic noborder nineforty&quot;&gt;
	&lt;p id=&quot;footer-nav&quot;&gt;
	    Copyright &#169; 2010 Stefan Priebsch &#183;
	    &lt;a href=&quot;http://www.priebsch.de/about&quot; title=&quot;Impressum&quot;&gt;Impressum&lt;/a&gt; &#183;
        &lt;a href=&quot;http://www.priebsch.de/about&quot; title=&quot;Kontakt&quot;&gt;Kontakt&lt;/a&gt;
    &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</subtitle>
			<link rel="self" href="http://www.priebsch.de/category/phpunit/feed/"/>
			<id>http://www.priebsch.de/category/phpunit/feed/</id>
			<updated>2010-01-07T21:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHP 5.3 BBQ Release Party Munich</title>
		<link href="http://www.frontalaufprall.com/2009/07/08/php-53-bbq-release-party-munich/"/>
		<id>http://www.frontalaufprall.com/?p=167</id>
		<updated>2009-07-08T05:51:17+00:00</updated>
		<content type="html">&lt;p&gt;Folks, it&amp;#8217;s Paaaaaaaaaaarty Time!&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;alignnone size-full wp-image-168&quot; title=&quot;asado&quot; src=&quot;http://www.frontalaufprall.com/wp-content/uploads/2009/07/asado.jpg&quot; alt=&quot;asado&quot; width=&quot;400&quot; height=&quot;265&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We like to invite you to the PHP 5.3 release party which is an event to&lt;br /&gt;
celebrate the 5.3 release, happening Friday, the 17th of July in Munich.&lt;br /&gt;
The release party offers a chance to come together with other php&lt;br /&gt;
enthusiasts and enjoy that php is alive and kicking. And of course people&lt;br /&gt;
in favour of a decent barbecue, together with some beer and other drinks&lt;br /&gt;
are invited.&lt;/p&gt;
&lt;p&gt;The happening will take place at &lt;a href=&quot;http://www.waldwirtschaft.de&quot; target=&quot;_blank&quot;&gt;Waldwirtschaft&lt;/a&gt; beer garden, at any weather. We will meet at 19:00 o&amp;#8217;clock - open end. The location is famous for its huge beer garden (2500 available seats, a children&#8217;s playground) and its typical Bavarian but also international food. On sunny weather you even may enjoy live-music and listen to the sounds of Jazz, Blues, Swing or Dixi.&lt;/p&gt;
&lt;p&gt;Catering will be provided and as a special delicacy you may enjoy a suckling pig!&lt;/p&gt;
&lt;p&gt;If you like to join the event please register at &lt;a href=&quot;http://phpugmunich.org/dokuwiki/php_release_party&quot; target=&quot;_blank&quot;&gt;PHPUG-Munich Wiki&lt;/a&gt; and follow it for updates.&lt;br /&gt;
Alternatively you may register at &lt;a href=&quot;http://www.facebook.com/event.php?eid=115203467104&quot; target=&quot;_blank&quot;&gt;Facebook&lt;/a&gt; as well and follow this for updates.&lt;/p&gt;
&lt;p&gt;For any questions please visit IRC channel: #phprp on irc.uni-erlangen.de.&lt;/p&gt;
&lt;p&gt;The PHP 5.3. BBQ release party is sponsored by:&lt;/p&gt;
&lt;p&gt;* &lt;a href=&quot;http://www.microsoft.com/php&quot; target=&quot;_blank&quot;&gt;Microsoft &lt;/a&gt;&lt;br /&gt;
* &lt;a href=&quot;http://www.mayflower.de/&quot; target=&quot;_blank&quot;&gt;Mayflower GmbH &lt;/a&gt;&lt;br /&gt;
* &lt;a href=&quot;http://www.swoodoo.com/de&quot; target=&quot;_blank&quot;&gt;Swoodoo AG &lt;/a&gt;&lt;br /&gt;
* &lt;a href=&quot;http://www.zend.de/&quot; target=&quot;_blank&quot;&gt;Zend Technologies GmbH&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Supporters for the PHP 5.3 BBQ release party are:&lt;/p&gt;
&lt;p&gt;&#8226; &lt;a href=&quot;http://www.sun.de/&quot; target=&quot;_blank&quot;&gt;Sun Microsystems&lt;/a&gt;&lt;br /&gt;
&#8226; &lt;a href=&quot;http://www.phpugmunich.org/&quot; target=&quot;_blank&quot;&gt;PHPUG.de&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I hope to see you there!&lt;/p&gt;
&lt;p&gt;Update: edited sponsor list&lt;/p&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<uri>http://www.frontalaufprall.com</uri>
		</author>
		<source>
			<title type="html">Frontalaufprall &#187; PHP related</title>
			<subtitle type="html">PHP, Agile Development und vorallem auch dies und das</subtitle>
			<link rel="self" href="http://www.frontalaufprall.com/category/php/feed/"/>
			<id>http://www.frontalaufprall.com/category/php/feed/</id>
			<updated>2010-03-15T00:00:23+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">The value of complexity metrics - Cyclomatic Complexity (1/2)</title>
		<link href="http://www.manuel-pichler.de/archives/55-The-value-of-complexity-metrics-Cyclomatic-Complexity-12.html"/>
		<id>http://www.manuel-pichler.de/archives/55-guid.html</id>
		<updated>2009-07-07T19:20:00+00:00</updated>
		<content type="html">&lt;p&gt;
  Software metrics are currently on everyone's lips and a frequently discussed topic. There are many conference talks, blog posts and other presentations that talk about software metrics. But to me it seems as if this subject is a closed book for many developers, so I decided to write this little post about a special category of software metrics, the complexity metrics.
&lt;/p&gt;
&lt;p&gt;
  Complexity metrics are a theoretical approach to measure the subjective complexity of a &lt;em&gt;software fragment&lt;/em&gt;, where the words &lt;em&gt;software fragment&lt;/em&gt; stand for a paraphrase for functions, methods, classes and nearly every logical unit that can be found in a software system. The most prevalent procedure to calculate complexity values is static code analysis, where an application parses the raw source code of a project, counts different statements and expressions and packs up the determined results in simple classification numbers. And with this information you already know the main concepts behind most software metrics, classification numbers and counting. As you can see there is no magic behind the scene, the only thing required is a good background knowledge to interpret those values.
&lt;/p&gt;
&lt;p&gt;
The &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2124&amp;entry_id=55&quot; title=&quot;Thomas J. McCabe: A Complexity Measure&quot;&gt;Cyclomatic Complexity Number&lt;/a&gt; or short CCN is the 
oldest complexity metrics. The first time this software 
metric was mentioned was 1976 by Thomas J. McCabe. This 
metric counts the available decision paths in a software 
fragment to determine its complexity. Each decision path 
starts with one of the conditional statements from the 
following list, so that it is fairly easy to detect them in
existing source code.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;?&lt;/li&gt;
  &lt;li&gt;case&lt;/li&gt;
  &lt;li&gt;elseif&lt;/li&gt;
  &lt;li&gt;for&lt;/li&gt;
  &lt;li&gt;foreach&lt;/li&gt;
  &lt;li&gt;if&lt;/li&gt;
  &lt;li&gt;while&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
A look at this list of statements may result in the questions:
Is this list wrong, it doesn't list &lt;code&gt;else&lt;/code&gt; and &lt;code&gt;default&lt;/code&gt;?
But it is correct. The assumption is that both statements
will contain the defaut execution path of a program which 
also exists when there are no special cases to capture.
&lt;/p&gt;

&lt;p&gt;
Each decision path gets the value &lt;em&gt;1&lt;/em&gt; and the sum of all these
values represents the Cyclomatic Complexity of the analyzed
software fragment. Note that each function and method also 
counts with a value of &lt;em&gt;1&lt;/em&gt; With this knowlegde we can now 
calculate the complexity of the following example code:
&lt;/p&gt;

&lt;div class=&quot;geshi&quot;&gt;&lt;ol&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;lt;?php&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt; CyclomaticComplexityNumber&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &lt;span&gt;public&lt;/span&gt; function exampe&lt;span&gt;&amp;#40;&lt;/span&gt; $x, $y &lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;// (1)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &lt;span&gt;&amp;#123;&lt;/span&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt; $x &amp;gt; &lt;span&gt;23&lt;/span&gt; || $y &amp;lt; &lt;span&gt;42&lt;/span&gt; &lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;// (1)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#123;&lt;/span&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;for&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt; $i = $x; $i &amp;gt;= $x &amp;amp;&amp;amp;amp; $i &amp;lt;= $y; ++$i &lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;// (1)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;else&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;switch&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt; $x + $y &lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;case&lt;/span&gt; &lt;span&gt;1&lt;/span&gt;: &lt;span&gt;// (1)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;case&lt;/span&gt; &lt;span&gt;2&lt;/span&gt;: &lt;span&gt;// (1)&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;default&lt;/span&gt;:&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; file_exists&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'/tmp/log'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt; or touch&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'/tmp/log'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;

&lt;p&gt;
Based on the previous definition the Cyclomatic Complexity
Number of the example code example is &lt;em&gt;5&lt;/em&gt;. But you may have
noticed that this approach does not capture all decision paths
that exist. We haven't catched those paths that came from the
by the boolean expression &lt;code&gt;||&lt;/code&gt; line 6 and &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; line 8, and
the logical &lt;code&gt;or&lt;/code&gt; expression in line 25. A variation of the
Cyclomatic Complexity Number that also captures those paths
is the so called CCN2. The CCN2 is the most widely used
variation of this software metrics. Tools like PHPUnit, PMD
and Checkstyle report it as Cyclomatic Complexity of an
analyzed software fragment.
&lt;/p&gt;

&lt;p&gt;
Now we get a complexity value of &lt;em&gt;8&lt;/em&gt; when we apply the CCN2
to the previous example, what is a growt of the software's
complexity of 60%.
&lt;/p&gt;

&lt;p&gt;
Due to the fact that Cyclomatic Complexity Number was
originally invented for procedural programming languages,
this definition for the Cyclomatic Complexity Number still
misses one element to measure the complexity of an object
oriented software system. With the concept of exceptions a
software gets additional decision paths for each &lt;code&gt;catch&lt;/code&gt;
statement used in the source code. While &lt;code&gt;try&lt;/code&gt; contains
the code for the regular execution code without special
cases, similar to &lt;code&gt;else&lt;/code&gt; and &lt;code&gt;default&lt;/code&gt; statements.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;?&lt;/li&gt;
  &lt;li&gt;&amp;amp;&amp;amp;&lt;/li&gt;
  &lt;li&gt;||&lt;/li&gt;
  &lt;li&gt;or&lt;/li&gt;
  &lt;li&gt;and&lt;/li&gt;
  &lt;li&gt;xor&lt;/li&gt;
  &lt;li&gt;case&lt;/li&gt;
  &lt;li&gt;catch&lt;/li&gt;
  &lt;li&gt;elseif&lt;/li&gt;
  &lt;li&gt;for&lt;/li&gt;
  &lt;li&gt;foreach&lt;/li&gt;
  &lt;li&gt;if&lt;/li&gt;
  &lt;li&gt;while&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Now that we know what the Cyclomatic Complexity Number is,
what can we do with the measured information? We can find
the complexity hotspots in a system, for example the top
ten artifacts with the highest complexity, but this is only
important during an initial analyses phase to get the big
picture of an application. For a continuous inspection this
information is not so important. A continuous analyses
requires thresholds that help to categories calculated
values. During the time four values have emerged as good
thresholds for the Cyclomatic Complexity Number of a
software system.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A software fragment with a CCN value between &lt;em&gt;1-4&lt;/em&gt; has
  low complexity.&lt;/li&gt;
  &lt;li&gt;A complexity value between &lt;em&gt;5-7&lt;/em&gt; is moderate and still
  easy to understand.&lt;/li&gt;
  &lt;li&gt;Everything between &lt;em&gt;6-10&lt;/em&gt; has a high complexity, while
  everything greater &lt;em&gt;10&lt;/em&gt; is very complex and hard to
  understand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
You may ask, why should I care about the complexity of a
software system, where is the value of benefit in this
metric?
&lt;/p&gt;

&lt;p&gt;
Mostly the complex parts of an application contain business
critical logic. But this complexity has negative impacts on
the readability and understandability of source code. Those
parts will normally become a maintainence and bug fixing
nightmare, because no one knows all the constraints, side
effects and what's exactly going on in that part of the
software. This situation results in the well known saying
&lt;em&gt;&quot;Never touch a running system&quot;&lt;/em&gt; which in turn mostly ends
in copy&amp;amp;paste programming. The situation can even become
more critical when the original author leaves the
development team or the company.
&lt;/p&gt;

&lt;p&gt;
Finally a small example how to apply the new knowledge
about the Cyclomatic Complexity Number, thresholds and the
negative impacts of complex software to an existing
development process. The following source listing shows
a complex method taken from PHP_Depend's source. This method
has a Cyclomatic Complexity Number of &lt;em&gt;16&lt;/em&gt; and I must admit
that the original author needed some time to understand what
was going on in this method.
&lt;/p&gt;

&lt;div class=&quot;geshi&quot;&gt;&lt;ol&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;lt;?php&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&lt;span&gt;private&lt;/span&gt; function _countCalls&lt;span&gt;&amp;#40;&lt;/span&gt;AbstractCallable $callable&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; $callT&amp;#160; = array&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; TokenizerI::T_STRING,&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; TokenizerI::T_VARIABLE&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; $chainT = array&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; TokenizerI::T_DOUBLE_COLON,&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; TokenizerI::T_OBJECT_OPERATOR,&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; $called = array&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; $tokens = $callable-&amp;gt;getTokens&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; $count&amp;#160; = count&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &lt;span&gt;for&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;$i = &lt;span&gt;0&lt;/span&gt;; $i &amp;lt; $count; ++$i&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;// break on function body open&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;type === TokenizerI::T_CURLY_BRACE_OPEN&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &lt;span&gt;for&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;; $i &amp;lt; $count; ++$i&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;// Skip non parenthesis tokens&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;type !== TokenizerI::T_PARENTHESIS_OPEN&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;continue&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;// Skip first token&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;!isset&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i - &lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt; || !in_array&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i - &lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;type, $callT&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;continue&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;// Count if no other token exists&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;!isset&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i - &lt;span&gt;2&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt; &amp;amp;&amp;amp;amp; !isset&lt;span&gt;&amp;#40;&lt;/span&gt;$called&lt;span&gt;&amp;#91;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i - &lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;image&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; $called&lt;span&gt;&amp;#91;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i - &lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;image&lt;span&gt;&amp;#93;&lt;/span&gt; = &lt;span&gt;true&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; ++$this-&amp;gt;_calls;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;continue&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt; &lt;span&gt;else&lt;/span&gt; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;in_array&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i - &lt;span&gt;2&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;type, $chainT&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; $identifier = $tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i - &lt;span&gt;2&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;image . $tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i - &lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;image;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;for&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;$j = $i - &lt;span&gt;3&lt;/span&gt;; $j &amp;gt;= &lt;span&gt;0&lt;/span&gt;; --$j&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;!in_array&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$j&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;type, $callT&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;amp;&amp;amp;amp; !in_array&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$j&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;type, $chainT&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; $identifier = $tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$j&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;image . $identifier;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;!isset&lt;span&gt;&amp;#40;&lt;/span&gt;$called&lt;span&gt;&amp;#91;&lt;/span&gt;$identifier&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; $called&lt;span&gt;&amp;#91;&lt;/span&gt;$identifier&lt;span&gt;&amp;#93;&lt;/span&gt; = &lt;span&gt;true&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; ++$this-&amp;gt;_calls;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt; &lt;span&gt;else&lt;/span&gt; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i - &lt;span&gt;2&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;type !== TokenizerI::T_NEW&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;amp;&amp;amp;amp; !isset&lt;span&gt;&amp;#40;&lt;/span&gt;$called&lt;span&gt;&amp;#91;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i - &lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;image&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; $called&lt;span&gt;&amp;#91;&lt;/span&gt;$tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i - &lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;image&lt;span&gt;&amp;#93;&lt;/span&gt; = &lt;span&gt;true&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; ++$this-&amp;gt;_calls;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;

&lt;p&gt;
The first thing to do is to make sure that the test suite
is good enough to ensure that the required refactorings
will not change the public behavior of the component or
class. When this is donw and we are sure our that api
breaks will be detected by the test suitewe can start to
extract logic into separate methods.
&lt;/p&gt;

&lt;p&gt;
The following example shows the result of the refactoring:
&lt;/p&gt;

&lt;div class=&quot;geshi&quot;&gt;&lt;ol&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;lt;?php&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&lt;span&gt;private&lt;/span&gt; function _countCalls&lt;span&gt;&amp;#40;&lt;/span&gt;AbstractCallable $callable&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; $called = array&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; $tokens = $callable-&amp;gt;getTokens&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; $count&amp;#160; = count&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &lt;span&gt;for&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;$i = $this-&amp;gt;_findOpenCurlyBrace&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens&lt;span&gt;&amp;#41;&lt;/span&gt;; $i &amp;lt; $count; ++$i&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;$this-&amp;gt;_isCallableOpenParenthesis&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens, $i&lt;span&gt;&amp;#41;&lt;/span&gt; === &lt;span&gt;false&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;continue&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;$this-&amp;gt;_isMethodInvocation&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens, $i&lt;span&gt;&amp;#41;&lt;/span&gt; === &lt;span&gt;true&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; $image = $this-&amp;gt;_getInvocationChainImage&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens, $i&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt; &lt;span&gt;else&lt;/span&gt; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;$this-&amp;gt;_isFunctionInvocation&lt;span&gt;&amp;#40;&lt;/span&gt;$tokens, $i&lt;span&gt;&amp;#41;&lt;/span&gt; === &lt;span&gt;true&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; $image = $tokens&lt;span&gt;&amp;#91;&lt;/span&gt;$i - &lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;-&amp;gt;image;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt; &lt;span&gt;else&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; $image = &lt;span&gt;null&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;if&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;$image !== &lt;span&gt;null&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; $called&lt;span&gt;&amp;#91;&lt;/span&gt;$image&lt;span&gt;&amp;#93;&lt;/span&gt; = $image;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; &lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160; &amp;#160; $this-&amp;gt;_calls += count&lt;span&gt;&amp;#40;&lt;/span&gt;$called&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&lt;span&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;div&gt;&amp;#160;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;

&lt;p&gt;
The subjective feeling of readability heavily depends on the
complexity of control structures, as we can see by a
comparison of the original and the refactored version of the
method example. The new version with its Cyclomatic Complexity
Number of &lt;em&gt;5&lt;/em&gt; is much easier to read and understand.
&lt;/p&gt;

&lt;p&gt;
This text is the first of two blog posts. The second article
will give a short introduction into the &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2125&amp;entry_id=55&quot; title=&quot;NPATH: a measure of execution path complexity and its applications&quot;&gt;NPath Complexity&lt;/a&gt;
You liked this article and you are interested in this and
other quality assurence related topics? - Then you should
now order your copy of the Book &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url=aHR0cDovL3F1YWxpdHlhc3N1cmFuY2VpbnBocHByb2plY3RzLmNvbQ==&amp;entry_id=55&quot; title=&quot;Quality Assurance in PHP Projects&quot;&gt;Quality Assurance in PHP 
Projects&lt;/a&gt;. The book talks about nearly all aspect of
quality assurence, with practical tips and expert knowledge
contributed by certain PHP professionals.
&lt;/p&gt;</content>
		<author>
			<name>Manuel Pichler</name>
			<email>nospam@example.com</email>
			<uri>http://www.manuel-pichler.de/</uri>
		</author>
		<source>
			<title type="html">Manuel Pichler - phpundercontrol</title>
			<subtitle type="html">Trust is good, (phpUnder)Control is better.</subtitle>
			<link rel="self" href="http://manuel-pichler.de/feeds/categories/10-phpundercontrol.rss"/>
			<id>http://manuel-pichler.de/feeds/categories/10-phpundercontrol.rss</id>
			<updated>2010-02-01T05:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en-us">
		<title type="html">Introduction to PHPUnit</title>
		<link href="http://szabgab.com/blog/2009/06/1245063912.html"/>
		<id>http://szabgab.com/blog/2009/06/1245063912.html</id>
		<updated>2009-06-15T04:05:12+00:00</updated>
		<content type="html">I am returning to the irregular postings of the &lt;a href=&quot;http://szabgab.com/test_automation_tips.html&quot;&gt;Test Automation Tips&lt;/a&gt;.
In this entry you can ready about simple introduction to the PHPUnit 
testing framework that is used, not surprisingly, to unit test PHP applications.


&lt;p&gt;For the full article visit &lt;a href=&quot;http://szabgab.com/blog/2009/06/1245063912.html&quot;&gt;Introduction to PHPUnit&lt;/a&gt;&lt;/p&gt;</content>
		<author>
			<name>Gabor Szabo</name>
			<uri>http://szabgab.com</uri>
		</author>
		<source>
			<title type="html">Blog of Gabor Szabo</title>
			<subtitle type="html">Gabor Szabo about Perl, automated testing, dynamic languages and everyting else</subtitle>
			<link rel="self" href="http://szabgab.com/blog/PHPUnit.rss"/>
			<id>http://szabgab.com/blog/PHPUnit.rss</id>
			<updated>2010-03-15T00:00:24+00:00</updated>
			<rights type="html">Copyright 2002-2010, Gabor Szabo</rights>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Does it ring a bell?</title>
		<link href="http://www.frontalaufprall.com/2009/06/13/does-it-ring-a-bell/"/>
		<id>http://www.frontalaufprall.com/?p=159</id>
		<updated>2009-06-13T10:05:19+00:00</updated>
		<content type="html">&lt;p&gt;This one reminds me on my past - after seeing it, I feel very happy that I do not do any contracting work any more. I still don&amp;#8217;t know if I should laugh or cry. It might be old - but nevertheless worth to watch it.&lt;/p&gt;
&lt;p&gt;(English - with German subtitles)&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;via &lt;a href=&quot;http://www.guido-muehlwitz.de/2009/06/links-der-woche-vi/&quot; target=&quot;_blank&quot;&gt;Guido Muehlwitz&lt;/a&gt;&lt;/p&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<uri>http://www.frontalaufprall.com</uri>
		</author>
		<source>
			<title type="html">Frontalaufprall &#187; PHP related</title>
			<subtitle type="html">PHP, Agile Development und vorallem auch dies und das</subtitle>
			<link rel="self" href="http://www.frontalaufprall.com/category/php/feed/"/>
			<id>http://www.frontalaufprall.com/category/php/feed/</id>
			<updated>2010-03-15T00:00:23+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit 3.3.17</title>
		<link href="http://sebastian-bergmann.de/archives/869-PHPUnit-3.3.17.html"/>
		<id>http://sebastian-bergmann.de/archives/869-guid.html</id>
		<updated>2009-06-06T08:30:00+00:00</updated>
		<content type="html">&lt;ul&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/386&quot; title=&quot;defect: parse error in eval while mocking SoapClient::__soapCall from ext/soap (closed: fixed)&quot;&gt;#386&lt;/a&gt;: Parse error in &lt;tt&gt;eval()&lt;/tt&gt; while mocking &lt;tt&gt;SoapClient::__soapCall&lt;/tt&gt;. &lt;a href=&quot;http://www.phpunit.de/changeset/4897&quot; title=&quot;- Merge [4895].&quot;&gt;[4897]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/782&quot; title=&quot;defect: DefaultDatabaseConnection.php missing ... (closed: fixed)&quot;&gt;#782&lt;/a&gt;: Missing include in &lt;tt&gt;DefaultDatabaseConnection.php&lt;/tt&gt;. &lt;a href=&quot;http://www.phpunit.de/changeset/4876&quot; title=&quot;- Merge [4874].&quot;&gt;[4876]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/783&quot; title=&quot;defect: Tests getting executed twice when using multiple groups (closed: fixed)&quot;&gt;#783&lt;/a&gt;: Tests getting executed twice when using multiple groups. &lt;a href=&quot;http://www.phpunit.de/changeset/4907&quot; title=&quot;- Merge [4905].&quot;&gt;[4907]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/801&quot; title=&quot;defect: PHPUnit_Util_Fileloader::load() fails silently when file doesn't exist (closed: fixed)&quot;&gt;#801&lt;/a&gt;: &lt;tt&gt;PHPUnit_Util_Fileloader::load()&lt;/tt&gt; fails silently when file does not exist. &lt;a href=&quot;http://www.phpunit.de/changeset/4928&quot; title=&quot;- Merge [4926].&quot;&gt;[4928]&lt;/a&gt; &lt;a href=&quot;http://www.phpunit.de/changeset/4929&quot; title=&quot;- Fix bad merge.&quot;&gt;[4929]&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Unit Testing Bad Practices by Example</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/15-Unit-Testing-Bad-Practices-by-Example.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/15-guid.html</id>
		<updated>2009-06-05T10:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;b&gt;This is an abstract for a chapter from a book on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Although &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_testing&quot;&gt;Unit Testing&lt;/a&gt; is a recommended practice for any software project, care has to be exercised such that testing yields the desired benefits. Bad programming practices in both test code and production code can make Unit Testing a nightmare. Maintenance of an overly complex test suite can easily become a burden to the project team.&lt;/p&gt;&lt;p&gt;Situations of hard to maintain test code can have extremely negative outcomes for project quality. Programmers start to ignore tests, because of their inconclusive description of what is going wrong. New features might not be tested at all, because writing tests for the current architecture considerably extends development time. In the end the project manager might decide to stop Unit Testing alltogether, because the costs outweight the benefits.&lt;/p&gt;&lt;p&gt;Bad practices of Unit Testing manifest in so called &quot;&lt;a href=&quot;http://xunitpatterns.com/Test%20Smells.html&quot;&gt;Test Smells&lt;/a&gt;&quot;. These are an early indicator of problems for long-run maintainability and utility of a project test suite. To constantly derive a benefit from Unit Tests, a commitment for high quality tests has to be made.&lt;/p&gt;&lt;p&gt;This case study will discuss Unit Testing bad practices and well as Test Smells and gives hints on how to avoid them. For each test smell, examples are shown from well-known PHP Open Source projects. As a result, the reader should be aware of the possible pitfalls of Unit Testing and that any test code requires the same care that is put into production code.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Benjamin Eberlei is a Project Lead with direkt effekt GmbH and contributes to the Zend Framework and other Open Source projects.&lt;/b&gt;&lt;/p&gt;</content>
		<author>
			<name>Benjamin Eberlei</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Testing Service-Oriented APIs</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/14-Testing-Service-Oriented-APIs.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/14-guid.html</id>
		<updated>2009-05-29T10:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;b&gt;This is an abstract for a chapter from a book on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;One of &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt;'s key strengths and differentiators in the crowded PHP framework arena is its offering of &lt;a href=&quot;http://en.wikipedia.org/wiki/Web_Service&quot;&gt;web service&lt;/a&gt; consumer components. As of version 1.8.0, these include offerings for &lt;a href=&quot;http://en.wikipedia.org/wiki/Action_Message_Format&quot;&gt;Adobe AMF&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Akismet&quot;&gt;Akismet&lt;/a&gt;, Amazon (including &lt;a href=&quot;http://en.wikipedia.org/wiki/Amazon_EC2&quot;&gt;EC2&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/Amazon_S3&quot;&gt;S3&lt;/a&gt; support), &lt;a href=&quot;http://en.wikipedia.org/wiki/AudioScrobbler&quot;&gt;AudioScrobbler&lt;/a&gt; from last.fm, &lt;a href=&quot;http://en.wikipedia.org/wiki/Delicious_%28website%29&quot;&gt;Del.icio.us&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Flickr&quot;&gt;Flickr&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/GData&quot;&gt;Google's GData&lt;/a&gt; services, &lt;a href=&quot;http://en.wikipedia.org/wiki/Nirvanix&quot;&gt;Nirvanix&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/ReCaptcha&quot;&gt;ReCaptcha&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Simpy&quot;&gt;Simpy&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Slideshare&quot;&gt;SlideShare&lt;/a&gt;, StrikeIron, &lt;a href=&quot;http://en.wikipedia.org/wiki/Technorati&quot;&gt;Technorati&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Twitter&quot;&gt;Twitter&lt;/a&gt;, and &lt;a href=&quot;http://en.wikipedia.org/wiki/Yahoo&quot;&gt;Yahoo!&lt;/a&gt; -- and more are planned or under development.&lt;/p&gt;&lt;p&gt;Offering components to interact with web services is relatively trivial -- but testing them offers a very different story. For &lt;a href=&quot;http://en.wikipedia.org/wiki/Continuous_Integration&quot;&gt;continuous integration&lt;/a&gt; purposes, it is typically better not to test against live services as this introduces network latency, and thus slows the testbed. Additionally, many services have API call limits, and automated test suites could easily rise far above these limits. There are also concerns about keeping sensitive API keys or credentials in the repository; some services are paid services, and such information would present a breach of security or contracts.&lt;/p&gt;&lt;p&gt;Over time, the Zend Framework team and contributors have developed a set of practices to address these issues that range from mocking the request and response payloads to offering different tests when credentials are provided via configuration. These practices can lead to well-tested service-oriented components and ensure that the end user experience is as documented.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Matthew Weier O'Phinney works for Zend Technologies Ltd. and is the Project Lead for the Zend Framework.&lt;/b&gt;&lt;/p&gt;</content>
		<author>
			<name>Matthew Weier O'Phinney</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">IPC09 - Why Architecture in Web Development matters</title>
		<link href="http://www.frontalaufprall.com/2009/05/27/ipc09-why-architecture-in-web-development-matters/"/>
		<id>http://www.frontalaufprall.com/?p=156</id>
		<updated>2009-05-27T09:28:28+00:00</updated>
		<content type="html">&lt;p&gt;IPC in Berlin is still in progress and I feel a bit wasted after too much alcohol during the last two days. I think I need a holiday to recover.&lt;/p&gt;
&lt;p&gt;For the ones interested - yesterday I had my talk about Architecture in Web Development - and here are the slides. Seems like slideshare ruined the layout when converting - sorry - you have to live with that. The slides probably won&amp;#8217;t be of much help if you did not attend the talk. Anyway - here we go:&lt;/p&gt;
&lt;div id=&quot;__ss_1494493&quot;&gt;&lt;a title=&quot;Why Architecture in Web Development matters&quot; href=&quot;http://www.slideshare.net/dodgeris/why-architecture-in-web-development-matters?type=presentation&quot;&gt;Why Architecture in Web Development matters&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;View more &lt;a href=&quot;http://www.slideshare.net/&quot;&gt;PDF documents&lt;/a&gt; from &lt;a href=&quot;http://www.slideshare.net/dodgeris&quot;&gt;dodgeris&lt;/a&gt;.&lt;/div&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<uri>http://www.frontalaufprall.com</uri>
		</author>
		<source>
			<title type="html">Frontalaufprall &#187; PHP related</title>
			<subtitle type="html">PHP, Agile Development und vorallem auch dies und das</subtitle>
			<link rel="self" href="http://www.frontalaufprall.com/category/php/feed/"/>
			<id>http://www.frontalaufprall.com/category/php/feed/</id>
			<updated>2010-03-15T00:00:23+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Continuous Integration with phpUnderControl</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/13-Continuous-Integration-with-phpUnderControl.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/13-guid.html</id>
		<updated>2009-05-22T10:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;b&gt;This is an abstract for a chapter from a book on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;One of the most important events in large and distributed team projects is the &lt;a href=&quot;http://en.wikipedia.org/wiki/System_integration&quot;&gt;integration&lt;/a&gt; of all parts of the software system into a release. Often incompatibilities and hard-to-detect errors surface at that very moment and can harm the success of the project. The remedy for this problem is the practice of &lt;a href=&quot;http://en.wikipedia.org/wiki/Continuous_Integration&quot;&gt;Continuous Integration&lt;/a&gt;: a merge of all parts of the system as often as possible during the lifecycle of the project.&lt;/p&gt;&lt;p&gt;In this case study, we will take a look into the preconditions to start with Continuous Integration as well as the procedural and technical rationales of this approach. We will take a look at entering Continuous Integration in PHP projects with &lt;a href=&quot;http://phpundercontrol.org/&quot;&gt;phpUnderControl&lt;/a&gt;, a customization of the popular and established Continuous Integration server software &lt;a href=&quot;http://cruisecontrol.sf.net/&quot;&gt;CruiseControl&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Beyond Continuous Integration, this case study introduces the reader to the principles of &lt;a href=&quot;http://en.wikipedia.org/wiki/Static_testing&quot;&gt;Static Testing&lt;/a&gt; and how to instrument it to gain a better &lt;a href=&quot;http://en.wikipedia.org/wiki/Software_quality&quot;&gt;quality&lt;/a&gt;. Amongst other tools, the reader will learn how to successfully use tools such as &lt;a href=&quot;http://pear.php.net/package/PHP_CodeSniffer&quot;&gt;PHP_CodeSniffer&lt;/a&gt;, &lt;a href=&quot;http://pdepend.org/&quot;&gt;PHP_Depend&lt;/a&gt; and &lt;a href=&quot;http://github.com/sebastianbergmann/phpcpd/&quot;&gt;phpcpd&lt;/a&gt; for &lt;a href=&quot;http://en.wikipedia.org/wiki/Static_code_analysis&quot;&gt;Static Code Analysis&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;In conclusion, advanced usage scenarios of the discussed tools will be discusses with a particular focus on how to foster further principles of &lt;a href=&quot;http://en.wikipedia.org/wiki/Agile_software_development&quot;&gt;Agile Software Development&lt;/a&gt; methodologies and how to solve discrepancies with other targets of agile methodologies.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Manuel Pichler is the creator of phpUnderControl, PHP_Depend, and phpmd. Sebastian Nohn is the Team Lead Quality Assurance at Ligatus GmbH.&lt;/b&gt;&lt;/p&gt;</content>
		<author>
			<name>Manuel Pichler and Sebastian Nohn</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Untestable Code</title>
		<link href="http://sebastian-bergmann.de/archives/865-Untestable-Code.html"/>
		<id>http://sebastian-bergmann.de/archives/865-guid.html</id>
		<updated>2009-05-20T21:00:00+00:00</updated>
		<content type="html">&lt;div id=&quot;__ss_1469139&quot;&gt;&lt;a href=&quot;http://www.slideshare.net/sebastian_bergmann/untestable-code?type=powerpoint&quot; title=&quot;Untestable Code&quot;&gt;Untestable Code&lt;/a&gt;&lt;!-- xhtml clean youtube --&gt;&lt;!-- /xhtml clean youtube --&gt;

&lt;!-- &lt;object style=&quot;margin:0px&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=untestablecode-090521062215-phpapp01&amp;amp;stripped_title=untestable-code&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=untestablecode-090521062215-phpapp01&amp;amp;stripped_title=untestable-code&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt; --&gt;

&lt;div&gt;View more &lt;a href=&quot;http://www.slideshare.net/&quot;&gt;Microsoft Word documents&lt;/a&gt; from &lt;a href=&quot;http://www.slideshare.net/sebastian_bergmann&quot;&gt;Sebastian Bergmann&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Speaking the Speaker&#8230;.</title>
		<link href="http://www.frontalaufprall.com/2009/05/17/speaking-the-speaker/"/>
		<id>http://www.frontalaufprall.com/?p=143</id>
		<updated>2009-05-17T09:33:34+00:00</updated>
		<content type="html">&lt;p&gt;Recently I had the chance to visit two SEO Conferences (&lt;a href=&quot;http://www.mediadonis.net/?p=400&quot; target=&quot;_blank&quot;&gt;smx&lt;/a&gt; and &lt;a href=&quot;http://semseo.abakus-internet-marketing.de/&quot; target=&quot;_blank&quot;&gt;semseo&lt;/a&gt;) here in Germany. Phew - I can tell you these people know how to party. Not that I do not enjoy the evenings at the php conferences I usually attend, but hey - when was the last time at a php conference where there was an &lt;a href=&quot;http://img198.imageshack.us/my.php?image=g8c.jpg&amp;via=tfrog&quot; target=&quot;_blank&quot;&gt;organized coyote ugly party&lt;/a&gt; and the crowd was filled up with tequila from nearly naked beautiful women? At least I can&amp;#8217;t remember. Followed by that I&amp;#8217;ve enjoyed a karaoke show where one of the organizers - &lt;a href=&quot;http://www.abakus-internet-marketing.de/&quot; target=&quot;_blank&quot;&gt;Alan Webb from Abakus&lt;/a&gt; presented his version of Sinatra&amp;#8217;s - or was it Sid Vicious? - version of &amp;#8216;My Way&amp;#8217;. Well - we definitly can learn from the SEO folks a lot about partying. Maybe we will enjoy Bjoern Schotte singing and dancing in Berlin? Would love to see this.&lt;/p&gt;
&lt;p&gt;Back to business - let&amp;#8217;s get a bit more serious.&lt;/p&gt;
&lt;p&gt;For me it was a quite unusual experience being a visitor and not one of the speakers so I could experience how difficult it is as a &amp;#8216;plain&amp;#8217; visitor to get into touch with the speakers. In every &amp;#8217;scene&amp;#8217; the speakers usually know each other for a quite long time and enjoy to meet again - so it is for me on the PHP Conferences. We gather, hang around, talk, drink and have fun. Nothing wrong with that. Only - if you are not a &amp;#8216;member&amp;#8217; of the speaker crowd it might feel a bit difficult to enter the conversation and get into touch with us. Especially developers tend to be bit shy - not much of us you could call &amp;#8216;extrovert&amp;#8217;. Humm&amp;#8230; well besides me.&lt;/p&gt;
&lt;p&gt;PHP is open source, driven by the community. And this is about you. Some of the speakers on the conferences around the world might contribute a bit more than you do - but nevertheless you are part of the community. So you are part of the &amp;#8216;crowd&amp;#8217; and so you should act.&lt;/p&gt;
&lt;p&gt;So if you want to get into touch with me for any reason then feel free to approach me any time. I will happily answer your questions, &lt;a href=&quot;http://www.frontalaufprall.com/2009/02/11/share-one-with-a-friend/&quot; target=&quot;_blank&quot;&gt;share a beer with you&lt;/a&gt; or will help you to get into contact with other people you are interested in.&lt;/p&gt;
&lt;p&gt;Next chance to meet me is on the &lt;a href=&quot;http://it-republik.de/php/phpconference/&quot; target=&quot;_blank&quot;&gt;IPC Spring Edition in Berlin&lt;/a&gt; next week. Hope to see you there!&lt;/p&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<uri>http://www.frontalaufprall.com</uri>
		</author>
		<source>
			<title type="html">Frontalaufprall &#187; PHP related</title>
			<subtitle type="html">PHP, Agile Development und vorallem auch dies und das</subtitle>
			<link rel="self" href="http://www.frontalaufprall.com/category/php/feed/"/>
			<id>http://www.frontalaufprall.com/category/php/feed/</id>
			<updated>2010-03-15T00:00:23+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Testing Symfony and Symfony Applications</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/11-Testing-Symfony-and-Symfony-Applications.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/11-guid.html</id>
		<updated>2009-05-08T10:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;b&gt;This is an abstract for a chapter from a book on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;In this case study, we will talk about how the &lt;a href=&quot;http://www.symfony-project.org/&quot;&gt;Symfony&lt;/a&gt; framework itself is tested, but also about the tools the framework provides to ease testing the customer applications.&lt;/p&gt;&lt;p&gt;Although developers are well educated now about tests, it is still the most neglected part of a web development process. Most developers still think they cannot afford writing tests because it takes too much time. The Symfony framework tries to ease the creation of both unit tests and functional tests with a unique and simple approach. For instance, functional tests are done by simulating a browser experience, but with the possibility to introspect all internal objects between each request. It is also possible to validate the generated content easily and precisely thanks to CSS3 selectors.&lt;/p&gt;&lt;p&gt;Testing the framework itself also proved to be quite challenging, and we learned it the hard way: from code that is too coupled to be tested thoroughly, to the usage of design patterns like the Singleton. Over the years, the Symfony framework quickly evolved from our testing experience, and now provides a well decoupled, but cohesive set of components. For Symfony 2, the introduction of a &lt;a href=&quot;http://en.wikipedia.org/wiki/Dependency_Injection&quot;&gt;Dependency Injection&lt;/a&gt; container will be of great help to ease the testing process even more.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Fabien Potencier is the CEO of Sensio and the lead developer of Symfony.&lt;/b&gt;&lt;/p&gt;</content>
		<author>
			<name>Fabien Potencier</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Faster TDD with Stakeout.rb</title>
		<link href="http://mikenaberezny.com/2007/09/04/faster-tdd-with-stakeout-rb/"/>
		<id>http://mikenaberezny.com/archives/78</id>
		<updated>2009-05-06T06:17:20+00:00</updated>
		<content type="html">&lt;p&gt;I&amp;#8217;m a big fan of &lt;a href=&quot;http://maintainable.com/articles/dry_up_testing_with_autotest&quot;&gt;Autotest&lt;/a&gt; and it runs almost constantly on my machine.  Autotest automatically reruns your tests whenever your files change.  Instead of constantly flipping to another shell to rerun your tests, just let Autotest cheerfully do it for you in the background.  It&amp;#8217;s highly addictive.&lt;/p&gt;
&lt;p&gt;The only problem with Autotest is that it is specific to Ruby.  At &lt;a href=&quot;http://maintainable.com&quot;&gt;work&lt;/a&gt;, I do a mix of different kinds of programming including Ruby, PHP, Python, and C.  I&amp;#8217;d like my TDD to be accelerated for all of these languages.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;http://nubyonrails.com/articles/automation-with-rstakeout&quot;&gt;Geoffrey Grossenbach&lt;/a&gt;, last week I came across &lt;a href=&quot;http://www.pragmaticautomation.com/cgi-bin/pragauto.cgi/Monitor/StakingOutFileChanges.rdoc&quot;&gt;stakeout.rb&lt;/a&gt; from &lt;a href=&quot;http://clarkware.com/cgi/blosxom&quot;&gt;Mike Clark&lt;/a&gt;.  This is a tiny, dead simple Ruby script that runs an arbitrary command when certain files change.  This is a stripped-down Autotest for everybody else.  I&amp;#8217;m sure it has all kinds of other uses as well.&lt;/p&gt;
&lt;p&gt;To get started testing with &lt;code&gt;stakeout.rb&lt;/code&gt;, you&amp;#8217;ll need &lt;a href=&quot;http://mikenaberezny.com/2007/09/04/faster-tdd-with-stakeout-rb/href&quot;&gt;Ruby&lt;/a&gt; installed.  Any recent version is fine and you might already have it installed.  Next, grab the &lt;a href=&quot;http://www.pragmaticautomation.com/cgi-bin/pragauto.cgi/Monitor/StakingOutFileChanges.rdoc&quot;&gt;stakeout.rb&lt;/a&gt; script and add the &lt;a href=&quot;http://en.wikipedia.org/wiki/Shebang_%28Unix%29&quot;&gt;shebang&lt;/a&gt; line to the top (Unix-like OS assumed):&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;ruby&quot;&gt;&lt;span&gt;#!/usr/bin/env ruby -w&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;if&lt;/span&gt; ARGV.&lt;span&gt;size&lt;/span&gt; &lt;span&gt;&amp;lt;&lt;/span&gt; &lt;span&gt;2&lt;/span&gt;
  &lt;span&gt;puts&lt;/span&gt; &lt;span&gt;&amp;quot;Usage: stakeout.rb &amp;lt;command&amp;gt; [files to watch]+&amp;quot;&lt;/span&gt;
...&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make the file executable and put it somewhere in your &lt;code&gt;PATH&lt;/code&gt;.  You can test it out by typing &lt;code&gt;stakeout.rb&lt;/code&gt; from an arbitrary directory and you should see the help message.&lt;/p&gt;
&lt;p&gt;Next, change over to a project directory where you have some test files.  Most of the projects that I am involved with tend to use some directory structure similar to this:&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;shell&quot;&gt;/project_name
  /lib
  /test
  ...&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To test such a project, run &lt;code&gt;stakeout.rb&lt;/code&gt; from the &lt;code&gt;/project_name&lt;/code&gt; directory.  Most PHP projects using PHPUnit tend to have an &lt;code&gt;AllTests.php&lt;/code&gt; file or equivalent to run all the tests, so we&amp;#8217;ll assume this for the example:&lt;/p&gt;

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;shell&quot;&gt;project_name$ stakeout.rb &amp;quot;php test/AllTests.php&amp;quot; **/*&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first argument is what command to run when the tests change.  The second argument, and any subsequent arguments, are the files to watch for changes.  These can use a Ruby &lt;a href=&quot;http://www.ruby-doc.org/core/classes/Dir.html#M002347&quot;&gt;globbing pattern&lt;/a&gt;.  The pattern &lt;code&gt;**/*&lt;/code&gt; will watch all files under &lt;code&gt;project_name&lt;/code&gt; recursively, which includes &lt;code&gt;lib/&lt;/code&gt; and &lt;code&gt;test/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Once &lt;code&gt;stakeout.rb&lt;/code&gt; is run, it will show no output but will sit and wait for changes.  As soon as you change a watched file, &lt;code&gt;stakeout.rb&lt;/code&gt; will automatically rerun you tests and will continue to do so until you exit with Control-C.&lt;/p&gt;</content>
		<author>
			<name>Mike Naberezny</name>
			<uri>http://mikenaberezny.com</uri>
		</author>
		<source>
			<title type="html">Mike Naberezny &#187; phpunit</title>
			<link rel="self" href="http://mikenaberezny.com/tag/phpunit/feed/atom/"/>
			<id>http://mikenaberezny.com/feed/atom/</id>
			<updated>2010-03-15T00:00:32+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">TYPO3: The Agile Future of a Ponderous Project</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/10-TYPO3-The-Agile-Future-of-a-Ponderous-Project.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/10-guid.html</id>
		<updated>2009-05-01T10:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;b&gt;This is an abstract for a chapter from a book on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;When Kasper Sk&#229;rh&#248;j wrote the first lines of PHP code laying the foundation for the &lt;a href=&quot;http://typo3.org/&quot;&gt;TYPO3&lt;/a&gt; CMS in 1998, he had not the slightest idea that a big part of the code he wrote would still be actively used ten years later. Adding the 3700 extensions contributed by an ever growing developer community resulted in an impressive amount of code - of varying quality.&lt;/p&gt;&lt;p&gt;Without surprise it soon became a challenge to assure a high quality and secure product. While the core developers were eager to add new features, the holy cow of backward compatibility was lurking at the next corner, waiting to be fed. The result is a feature-rich and solid but equally monolithic and complex pile of code that is, at best, hard to test. As a consequence we decided to rewrite TYPO3 from scratch.&lt;/p&gt;&lt;p&gt;In this case study we will share our experience with the technical and organisational techniques we have chosen for the development of TYPO3 version 5 and its foundation, the &lt;a href=&quot;http://flow3.typo3.org/&quot;&gt;FLOW3&lt;/a&gt; framework. It explains our pedantic pursuit of clean code, outlines our commit and coding guidelines and gives answers to tricky situations you face while writing and maintaining (true) &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_testing&quot;&gt;unit tests&lt;/a&gt;. Finally we demonstrate how a clean architecture can help you tackling the complexity of your application.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Robert Lemke and Karsten Dambekalns are core developers of both TYPO3 and FLOW3.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;A few recipes for writing good unit tests that are part of this case study are demonstrated in the &quot;Delicious Test Recipes&quot; episode of &lt;a href=&quot;http://typo3.org/podcasts/robert/&quot;&gt;Robert Lemke's podcast&lt;/a&gt;.&lt;/p&gt;</content>
		<author>
			<name>Robert Lemke and Karsten Dambekalns</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Testing the ezcGraph Component</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/8-Testing-the-ezcGraph-Component.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/8-guid.html</id>
		<updated>2009-04-17T10:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;b&gt;This is an abstract for a chapter from a book on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;The &lt;a href=&quot;http://ezcomponents.org/docs/tutorials/Graph&quot;&gt;Graph&lt;/a&gt; component from the &lt;a href=&quot;http://ezcomponents.org/docs/tutorials/Graph&quot;&gt;eZ Components&lt;/a&gt; project provides an easy to use and extensible library for creating graphical charts. In the eZ Components project we aim to develop test-driven, which resulted in two challenges developing this library.&lt;/p&gt;&lt;p&gt;The output generated by a Graph component is an image, which in most cases is binary-encoded data. Expectations are really hard to create by hand, it is only feasible to create functional tests replaying once created data. The actual image is generated by external libraries such as &lt;code&gt;ext/gd&lt;/code&gt;. These external libraries may change their exact output at any time, or even between two runs with the same version of the library. Comparisons of the generated images need to respect that and implement special assertions for the given type of binary data.&lt;/p&gt;&lt;p&gt;Testing the created binary data has proven to be prone to errors. Since the actual image generation has been abstracted away, we are able to use of different image creation mechanisms. Thanks to the &lt;a href=&quot;http://www.phpunit.de/manual/current/en/test-doubles.html&quot;&gt;support for mock objects&lt;/a&gt; in &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt;, all calls to the driver layer can be checked for correctness without actually generating images.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Kore Nordmann is an active member of the PHP community and works for eZ Systems on the eZ Components.&lt;/b&gt;&lt;/p&gt;</content>
		<author>
			<name>Kore Nordmann</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit 3.3.16</title>
		<link href="http://sebastian-bergmann.de/archives/861-PHPUnit-3.3.16.html"/>
		<id>http://sebastian-bergmann.de/archives/861-guid.html</id>
		<updated>2009-04-10T11:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/712&quot; title=&quot;defect: Custom TestCase base classes are not handled properly (closed: fixed)&quot;&gt;#712&lt;/a&gt;: Custom TestCase base classes are not handled properly. &lt;a href=&quot;http://www.phpunit.de/changeset/4790&quot; title=&quot;- Merge [4788].&quot;&gt;[4790]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/728&quot; title=&quot;defect: Loading Selenium test suite from config file does not work (...again) (closed: fixed)&quot;&gt;#728&lt;/a&gt;: Loading Selenium test suite from config file does not work. &lt;a href=&quot;http://www.phpunit.de/changeset/4686&quot; title=&quot;- Merge [4684].&quot;&gt;[4686]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/736&quot; title=&quot;defect: Regression in test autoloading (closed: fixed)&quot;&gt;#736&lt;/a&gt;: Regression in test autoloading. &lt;a href=&quot;http://www.phpunit.de/changeset/4787&quot; title=&quot;- Merge [4785].&quot;&gt;[4787]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/737&quot; title=&quot;defect: Diff operation fails when /tmp is not writable (closed: fixed)&quot;&gt;#737&lt;/a&gt;: Diff operation fails when &lt;tt&gt;/tmp&lt;/tt&gt; is not writable. &lt;a href=&quot;http://www.phpunit.de/changeset/4748&quot; title=&quot;- Merge [4746].&quot;&gt;[4748]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/758&quot; title=&quot;defect: Wrong double quotes on oracle statements (closed: fixed)&quot;&gt;#758&lt;/a&gt;: Wrong double quotes on Oracle statements. &lt;a href=&quot;http://www.phpunit.de/changeset/4784&quot; title=&quot;- Merge [4781] and [4782].&quot;&gt;[4784]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/759&quot; title=&quot;defect: DBUnit load constraint definitions of others schemas (closed: fixed)&quot;&gt;#759&lt;/a&gt;: DBUnit loads constraint definitions of others schemas. &lt;a href=&quot;http://www.phpunit.de/changeset/4784&quot; title=&quot;- Merge [4781] and [4782].&quot;&gt;[4784]&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Quality Assurance at Digg Inc.</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/7-Quality-Assurance-at-Digg-Inc..html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/7-guid.html</id>
		<updated>2009-04-10T10:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;b&gt;This is an abstract for a chapter from a book on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://www.digg.com/&quot;&gt;Digg&lt;/a&gt;'s development philosophy has changed dramatically in the last year in an attempt to move towards a more &lt;a href=&quot;http://en.wikipedia.org/wiki/Agile_software_development&quot;&gt;agile&lt;/a&gt; and iterative approach. A large part of these sweeping changes is moving toward a &lt;a href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;test-driven development&lt;/a&gt; methodology with a minimum of 80% &lt;a href=&quot;http://en.wikipedia.org/wiki/Code_Coverage&quot;&gt;code coverage&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Integrating &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_testing&quot;&gt;unit testing&lt;/a&gt; into coding practices is a daunting task at first glance. It requires adjusting how developers work in almost every respect, but it can also greatly assist in debugging and validating your code. We wanted to get this right the first time, so we decided to hire an outside contractor to help us formulate a plan of attack. Once we decided upon a course of action, it took only a week for the contractor and two developers to build a test harness and small suite of tests for our core classes, we even found a handful of bugs along the way. Next, we worked to instruct the remaining developers at Digg of best practices for writing unit tests.&lt;/p&gt;&lt;p&gt;Although in one week we went from having only a handful of previously written tests to having a framework to build unit tests much more easily, our work was far from complete. Even our QA team has dramatically changed how they operate to take advantage of the benefits unit testing offers.&lt;/p&gt;&lt;p&gt;Our case study will discuss in depth benefits and drawbacks of adopting test-driven development, cover the gamut of unit testing from simple assertions to mocking complex objects, and dissect the continuing challenges we face.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Robert Balousek, Matt Erkkila, Ian Eure, Bill Shupp, Jeremy McCarthy and Brian O'Neill all contributed to the case study and are employees of Digg.&lt;/b&gt;&lt;/p&gt;</content>
		<author>
			<name>Robert Balousek, Matt Erkkila, Ian Eure, Bill Shupp, Jeremy McCarthy and Brian O'Neill</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Large-Scale Selenium-Based Testing</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/6-Large-Scale-Selenium-Based-Testing.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/6-guid.html</id>
		<updated>2009-04-03T10:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;b&gt;This is an abstract for a chapter from a book on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;A well established practice in web application development is testing a web-based GUI as a whole in order to ensure its functionality.&lt;/p&gt;&lt;p&gt;At studiVZ, we have to test three different platforms in two languages. There are many platform-specific differences, in both wording and functionality. The scenario is even further complicated by the use of AJAX functionality in some features. With a release cycle of 14 days, this is indeed a challenge for a small quality assurance team.&lt;/p&gt;&lt;p&gt;In addition to &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_testing&quot;&gt;Unit Tests&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Acceptance_testing&quot;&gt;Acceptance Tests&lt;/a&gt; are the main part of our automated testing strategy. There are thousands of acceptance tests that have been written since the rewrite of the platform in early 2008. Because of our special requirements (tests have to work for three platforms) we decided not to use one of these capture-and-replay web testing softwares but to write our tests by hand. We chose &lt;a href=&quot;http://seleniumhq.org/projects/remote-control/&quot;&gt;Selenium RC&lt;/a&gt; and the &lt;a href=&quot;http://www.phpunit.de/manual/current/en/selenium.html&quot;&gt;Selenium RC extension for PHPUnit&lt;/a&gt; that allows to write and execute acceptance tests in a unit test style.&lt;/p&gt;&lt;p&gt;But writing acceptance tests is a rocky road to success. The main problem with acceptance tests is their fragility: they will break when the code changes. Another challenge is keeping the tests maintainable, foremost readable. This was the motivation to create a domain-specific language for PHP that allows us to write tests in the language of our business rather than in Selenium's language.&lt;/p&gt;&lt;p&gt;We want to share our insight into the specific challenges of acceptance testing and how to handle them. Furthermore we will talk about our experiences and learning curve with a DSL-based framework for Selenium tests.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Christiane Philipps is the Team Lead Quality Assurance and Max Horv&#225;th is the Team Lead Mobile Development at studiVZ Ltd.&lt;/b&gt;&lt;/p&gt;</content>
		<author>
			<name>Christiane Philipps and Max Horv&#225;th</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Testing Database Interaction</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/5-Testing-Database-Interaction.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/5-guid.html</id>
		<updated>2009-03-27T11:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;b&gt;This is an abstract for a chapter from a book on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Proper interaction with &lt;a href=&quot;http://en.wikipedia.org/wiki/RDBMS&quot;&gt;relational databases&lt;/a&gt; is incredibly important in most pieces of software. The importance of this interaction is underscored by the fact that many software architectures have at least one entire layer or system devoted to data persistence and data loading. When dealing with critical data in enterprise level applications it becomes even more important to make sure your data is being stored and retrieved correctly.&lt;/p&gt;&lt;p&gt;As responsible developers, one of our goals should be to test database interaction and test it well. To help achieve this goal, we will take a close look at tools and techniques that can be used with projects of any size to help create reliable tests capable of validating your database interaction.&lt;/p&gt;&lt;p&gt;The discussion will begin with various techniques for testing your database layer. The focus will then move toward the functionality in the &lt;a href=&quot;http://www.phpunit.de/manual/current/en/database.html&quot;&gt;database extension&lt;/a&gt; for &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt;. Then, utilizing the tools provided in the database extension, examples will be given of how to create basic tests validating that the database is correctly manipulated and data from your database is successfully retrieved. This will be followed by an in depth discussion of &quot;best practices&quot; that can be utilized when you are developing &quot;database aware&quot; fixtures and tests.&lt;/p&gt;&lt;p&gt;Once the ground work is laid, we will look at how all of these tools and techniques can be utilized in both your &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_testing&quot;&gt;unit tests&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/System_testing&quot;&gt;functional tests&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Michael Lively Jr. is the Lead PHP Developer for Selling Source, LLC.&lt;/b&gt;&lt;/p&gt;</content>
		<author>
			<name>Michael Lively Jr.</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Bye Bye bella Roma</title>
		<link href="http://www.frontalaufprall.com/2009/03/21/bye-bye-bella-roma/"/>
		<id>http://www.frontalaufprall.com/?p=135</id>
		<updated>2009-03-21T08:17:42+00:00</updated>
		<content type="html">&lt;p&gt;The last few days I had the pleasure to visit the &lt;a href=&quot;http://www.phpcon.it&quot; target=&quot;_blank&quot;&gt;PHP Conference&lt;/a&gt; in Rome. It was - as usual - really good organized and even though it was not that big as other conferences I personally think that it was quite successful. And for sure the location&amp;#8230; thousands of years of culture. There is simply no other city in the world with the age and the cultural background like Rome.&lt;/p&gt;
&lt;p&gt;As promised here are my presentations:&lt;/p&gt;
&lt;div id=&quot;__ss_1177158&quot;&gt;&lt;a title=&quot;Why Architecture Matters&quot; href=&quot;http://www.slideshare.net/dodgeris/why-architecture-matters?type=powerpoint&quot;&gt;Why Architecture Matters&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;View more &lt;a href=&quot;http://www.slideshare.net/&quot;&gt;presentations&lt;/a&gt; from &lt;a href=&quot;http://www.slideshare.net/dodgeris&quot;&gt;dodgeris&lt;/a&gt;.&lt;/div&gt;

&lt;div id=&quot;__ss_1177157&quot;&gt;&lt;a title=&quot;Monitor Your Business V2&quot; href=&quot;http://www.slideshare.net/dodgeris/monitor-your-business-v2?type=presentation&quot;&gt;Monitor Your Business V2&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;View more &lt;a href=&quot;http://www.slideshare.net/&quot;&gt;presentations&lt;/a&gt; from &lt;a href=&quot;http://www.slideshare.net/dodgeris&quot;&gt;dodgeris&lt;/a&gt;.&lt;/div&gt;

&lt;p&gt;( V2 as this is an improved version now with better examples using &lt;a href=&quot;http://www.oxid-esales.com/download&quot; target=&quot;_blank&quot;&gt;OXID eShop&lt;/a&gt; to show the power of selfmade Nagios/Cacti plugins)&lt;/p&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<uri>http://www.frontalaufprall.com</uri>
		</author>
		<source>
			<title type="html">Frontalaufprall &#187; PHP related</title>
			<subtitle type="html">PHP, Agile Development und vorallem auch dies und das</subtitle>
			<link rel="self" href="http://www.frontalaufprall.com/category/php/feed/"/>
			<id>http://www.frontalaufprall.com/category/php/feed/</id>
			<updated>2010-03-15T00:00:23+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Testing a WebDAV Server</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/4-Testing-a-WebDAV-Server.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/4-guid.html</id>
		<updated>2009-03-20T11:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;b&gt;This is an abstract for a chapter from a book on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;The &lt;a href=&quot;http://ezcomponents.org/&quot;&gt;eZ Components&lt;/a&gt; project was started with the goal to create a high-quality set of independent building blocks for PHP 5 based application development. Making extensive use of &lt;a href=&quot;http://en.wikipedia.org/wiki/Unit_testing&quot;&gt;unit tests&lt;/a&gt; and sticking to strict development and documentation standards were defined as the basic methodology. One of the biggest challenges in terms of testing and quality assurance so far was the &lt;a href=&quot;http://ezcomponents.org/docs/tutorials/Webdav&quot;&gt;eZ Webdav&lt;/a&gt; component.&lt;/p&gt;&lt;p&gt;The eZ Webdav component is intended to provide a modular &lt;a href=&quot;http://en.wikipedia.org/wiki/WebDAV&quot;&gt;WebDAV&lt;/a&gt; server to be embedded in any kind of web application. Its architecture is built to be as customizable and extensible as possible, while it tries on the other hand to compensate the weaknesses of the RFC and common WebDAV clients.&lt;/p&gt;&lt;p&gt;Testing a server is a challenge in general. Testing the WebDAV component brought us to the limit of unit testing and forced us to find new ways of using &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt; to ensure code quality and to obviate regressions. Unavoidable deep code dependencies in some parts of the server enforced the extensive use of &lt;a href=&quot;http://en.wikipedia.org/wiki/Mock_object&quot;&gt;mock objects&lt;/a&gt; to stick to the unit test paradigm. In some areas, like avoiding regressions in the adjusted behavior against special clients, unit testing was even impossible. For this reason, special record/playback-based tests were created and implemented using PHPUnit.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Tobias Schlitt is an active member of the PHP community and works for eZ Systems on the eZ Components.&lt;/b&gt;&lt;/p&gt;</content>
		<author>
			<name>Tobias Schlitt</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Quality Assurance in PHP Projects</title>
		<link href="http://sebastian-bergmann.de/archives/857-Quality-Assurance-in-PHP-Projects.html"/>
		<id>http://sebastian-bergmann.de/archives/857-guid.html</id>
		<updated>2009-03-18T17:00:00+00:00</updated>
		<content type="html">&lt;div id=&quot;__ss_1163460&quot;&gt;&lt;a href=&quot;http://www.slideshare.net/sebastian_bergmann/quality-assurance-in-php-projects-1163460?type=powerpoint&quot; title=&quot;Quality Assurance in PHP Projects&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;&lt;!-- xhtml clean youtube --&gt;&lt;!-- /xhtml clean youtube --&gt;

&lt;!-- &lt;object style=&quot;margin:0px&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slideshare.net/swf/ssplayer2.swf?doc=qualityassuranceinphpprojects-090318104047-phpapp02&amp;amp;stripped_title=quality-assurance-in-php-projects-1163460&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed src=&quot;http://static.slideshare.net/swf/ssplayer2.swf?doc=qualityassuranceinphpprojects-090318104047-phpapp02&amp;amp;stripped_title=quality-assurance-in-php-projects-1163460&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt; --&gt;

&lt;div&gt;View more &lt;a href=&quot;http://www.slideshare.net/&quot;&gt;presentations&lt;/a&gt; from &lt;a href=&quot;http://www.slideshare.net/sebastian_bergmann&quot;&gt;Sebastian Bergmann&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Quality Assurance Tools for PHP</title>
		<link href="http://sebastian-bergmann.de/archives/856-Quality-Assurance-Tools-for-PHP.html"/>
		<id>http://sebastian-bergmann.de/archives/856-guid.html</id>
		<updated>2009-03-15T07:50:21+00:00</updated>
		<content type="html">&lt;a href=&quot;http://www.flickr.com/photos/sebastian_bergmann/3356003644/&quot; title=&quot;Map of PHP QA Tools by Sebastian Bergmann, on Flickr&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3552/3356003644_8c4c5af0b3.jpg&quot; width=&quot;500&quot; height=&quot;147&quot; alt=&quot;Map of PHP QA Tools&quot; /&gt;&lt;/a&gt;

&lt;p&gt;The map above contains the following tools that are useful for quality assurance in PHP projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://pear.php.net/package/PHP_CodeSniffer&quot;&gt;PHP_CodeSniffer&lt;/a&gt; tokenises PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://phpmd.org/&quot;&gt;phpmd&lt;/a&gt; scans PHP source code and looks for potential problems such as possible bugs, suboptimal code or overcomplicated expressions.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/sebastianbergmann/phpcpd/&quot;&gt;phpcpd&lt;/a&gt; is a Copy/Paste Detector (CPD) for PHP code.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://pdepend.org/&quot;&gt;PHP_Depend&lt;/a&gt; is a PHP software metrics tool.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt; is the de-facto standard unit test framework for PHP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Build_automation&quot;&gt;Build Automation&lt;/a&gt; is the act of scripting or automating a wide variety of tasks that a software developer will do in their day-to-day activities, including tasks that involve the tools listed above.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ant.apache.org/&quot;&gt;Apache Ant&lt;/a&gt; is a Java-based build tool that is similar to &lt;a href=&quot;http://en.wikipedia.org/wiki/Make_%28software%29&quot;&gt;make&lt;/a&gt;, but without make's wrinkles. Its build files are XML-based, calling out a target tree where various tasks get executed.&lt;/p&gt;
&lt;p&gt;The listing below shows an Apache Ant build file for a project named &lt;code&gt;Money&lt;/code&gt;.&lt;/p&gt;

&lt;dl&gt;&lt;dd&gt;&lt;pre&gt;&amp;lt;project name=&quot;Money&quot; default=&quot;build&quot;&amp;gt;
 &amp;lt;target name=&quot;clean&quot;&amp;gt;
  &amp;lt;delete dir=&quot;${basedir}/build&quot;/&amp;gt;
 &amp;lt;/target&amp;gt;

 &amp;lt;target name=&quot;prepare&quot;&amp;gt;
  &amp;lt;mkdir dir=&quot;${basedir}/build/logs&quot;/&amp;gt;
 &amp;lt;/target&amp;gt;

 &amp;lt;target name=&quot;phpcs&quot;&amp;gt;
  &amp;lt;exec dir=&quot;${basedir}&quot;
        executable=&quot;phpcs&quot;
        output=&quot;${basedir}/build/logs/checkstyle.xml&quot;
        failonerror=&quot;false&quot;&amp;gt;
   &amp;lt;arg line=&quot;--report=checkstyle .&quot;/&amp;gt;
  &amp;lt;/exec&amp;gt;
 &amp;lt;/target&amp;gt;

 &amp;lt;target name=&quot;phpmd&quot;&amp;gt;
  &amp;lt;exec dir=&quot;${basedir}&quot;
        executable=&quot;phpmd&quot;
        failonerror=&quot;false&quot;&amp;gt;
   &amp;lt;arg line=&quot;. xml codesize
              --reportfile ${basedir}/build/logs/pmd.xml&quot;/&amp;gt;
  &amp;lt;/exec&amp;gt;
 &amp;lt;/target&amp;gt;

 &amp;lt;target name=&quot;phpcpd&quot;&amp;gt;
  &amp;lt;exec dir=&quot;${basedir}&quot;
        executable=&quot;phpcpd&quot;
        failonerror=&quot;false&quot;&amp;gt;
   &amp;lt;arg line=&quot;--log-pmd=${basedir}/build/logs/pmd-cpd.xml .&quot;/&amp;gt;
  &amp;lt;/exec&amp;gt;
 &amp;lt;/target&amp;gt;

 &amp;lt;target name=&quot;pdepend&quot;&amp;gt;
  &amp;lt;exec dir=&quot;${basedir}&quot;
        executable=&quot;pdepend&quot;
        failonerror=&quot;false&quot;&amp;gt;
   &amp;lt;arg line=&quot;--jdepend-xml=${basedir}/build/logs/jdepend.xml .&quot;/&amp;gt;
  &amp;lt;/exec&amp;gt;
 &amp;lt;/target&amp;gt;

 &amp;lt;target name=&quot;phpunit&quot;&amp;gt;
  &amp;lt;exec dir=&quot;${basedir}&quot;
        executable=&quot;phpunit&quot;
        failonerror=&quot;true&quot;&amp;gt;
   &amp;lt;arg line=&quot;--log-xml         ${basedir}/build/logs/junit.xml
              --coverage-clover ${basedir}/build/logs/clover.xml
              MoneyTest&quot;/&amp;gt;
  &amp;lt;/exec&amp;gt;
 &amp;lt;/target&amp;gt;

 &amp;lt;target name=&quot;build&quot;
         depends=&quot;clean,prepare,phpcs,phpmd,phpcpd,pdepend,phpunit&quot;/&amp;gt;
&amp;lt;/project&amp;gt;&lt;/pre&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;The main target, &lt;code&gt;build&lt;/code&gt;, depends on the targets that&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Delete the &lt;code&gt;build&lt;/code&gt; directory, if it exists.&lt;/li&gt;
&lt;li&gt;Prepare the &lt;code&gt;build&lt;/code&gt; directory, if it does not exist.&lt;/li&gt;
&lt;li&gt;Run PHP_CodeSniffer on the project's sourcecode and write a logfile in &lt;a href=&quot;http://checkstyle.sourceforge.net/&quot;&gt;Checkstyle&lt;/a&gt; XML format.&lt;/li&gt;
&lt;li&gt;Run phpmd on the project's sourcecode and write a logfile in &lt;a href=&quot;http://pmd.sourceforge.net/&quot;&gt;PMD&lt;/a&gt; XML format.&lt;/li&gt;
&lt;li&gt;Run phpcpd on the project's sourcecode and write a logfile in &lt;a href=&quot;http://pmd.sourceforge.net/&quot;&gt;PMD-CPD&lt;/a&gt; XML format.&lt;/li&gt;
&lt;li&gt;Run PHP_Depend on the project's sourcecode and write a logfile in &lt;a href=&quot;http://clarkware.com/software/JDepend.html&quot;&gt;JDepend&lt;/a&gt; XML format.&lt;/li&gt;
&lt;li&gt;Run the project's tests using PHPUnit and write logfiles in &lt;a href=&quot;http://junit.org/&quot;&gt;JUnit&lt;/a&gt; XML and &lt;a href=&quot;http://www.atlassian.com/software/clover/&quot;&gt;Clover&lt;/a&gt; XML format.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below is the output for invoking Apache Ant in the project directory:&lt;/p&gt;

&lt;dl&gt;&lt;dd&gt;&lt;pre&gt;sb@ubuntu Money % ant
Buildfile: build.xml

clean:
   [delete] Deleting directory /home/sb/Money/build

prepare:
    [mkdir] Created dir: /home/sb/Money/build/logs

phpcs:

phpmd:

phpcpd:
     [exec] phpcpd 1.1.0 by Sebastian Bergmann.
     [exec] 
     [exec] 0.00% duplicated lines out of 722 total lines of code.

pdepend:
     [exec] PHP_Depend 0.9.4 by Manuel Pichler
     [exec] 
     [exec] Executing Dependency-Analyzer:
     [exec]                                                                 16
     [exec] 
     [exec] Generating pdepend log files, this may take a moment.

phpunit:
     [exec] PHPUnit 3.4.0 by Sebastian Bergmann.
     [exec] 
     [exec] ......................
     [exec] 
     [exec] Time: 0 seconds
     [exec] 
     [exec] OK (22 tests, 34 assertions)
     [exec] 
     [exec] Writing code coverage data to XML file, this may take a moment.

build:

BUILD SUCCESSFUL
Total time: 4 seconds&lt;/pre&gt;&lt;/dd&gt;&lt;/dl&gt;

&lt;p&gt;The generated logfiles can be processed by &lt;a href=&quot;http://cruisecontrol.sourceforge.net/&quot;&gt;CruiseControl&lt;/a&gt; because it already knows the XML formats used. &lt;a href=&quot;http://phpundercontrol.org/&quot;&gt;phpUnderControl&lt;/a&gt; is a customization of CruiseControl that caters to the needs of PHP projects and makes a lot of things easier.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://sonar.codehaus.org/&quot;&gt;Sonar&lt;/a&gt; enables to collect, analyze and report metrics on source code. It not only offers consolidated reporting on and across projects throughout time, but it becomes the central place to manage code quality. The developers of Sonar are working on &lt;a href=&quot;http://jira.codehaus.org/browse/SONARPLUGINS-31&quot;&gt;out-of-the-box support for PHP projects&lt;/a&gt;.&lt;/p&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">swoodoo - A True Agile Story</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/3-swoodoo-A-True-Agile-Story.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/3-guid.html</id>
		<updated>2009-03-13T11:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;b&gt;This is an abstract for a chapter from a book on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://www.swoodoo.com/&quot;&gt;swoodoo&lt;/a&gt;, the Germany-based flight search engine, has gone through a wild evolution. In 2003 it started out as a peer-to-peer network with ActiveX browser plugins written in C++ to query cheap flights. It went through a Java-centric solution using various techniques for screenscraping data from airline websites and finally has evolved into a robust architecture where Java and MySQL are used in the backend and PHP plays a major role in all frontend-related tasks as well as in data gathering from airlines.&lt;/p&gt;&lt;p&gt;Besides technology, the software architecture has also changed immensely: from distributed objects to a &quot;&lt;a href=&quot;http://en.wikipedia.org/wiki/Big_ball_of_mud&quot;&gt;big ball of mud&lt;/a&gt;&quot; and finally into a &lt;a href=&quot;http://en.wikipedia.org/wiki/Service-oriented_architecture&quot;&gt;Service-Oriented Architecture (SOA)&lt;/a&gt; with clearly defined interfaces between separate services. In order to have a better control of swoodoo evolution, project management was switched to &lt;a href=&quot;http://en.wikipedia.org/wiki/Extreme_Programming&quot;&gt;Extreme Programming (XP)&lt;/a&gt; in the beginning of 2007. At the same time we introduced unit testing using &lt;a href=&quot;http://junit.org/&quot;&gt;JUnit&lt;/a&gt; and &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt; as well as PHP-driven &lt;a href=&quot;http://seleniumhq.org/&quot;&gt;Selenium&lt;/a&gt; acceptance testing. Initially we made heavy use of Selenium but recently we have reduced the amount of Selenium tests - a tradeoff we had to make because of the nature of our SOA-based architecture.&lt;/p&gt;&lt;p&gt;In this case study we want to show the evolution of our agile management techniques, testing environment, tools and approaches we use and why we decided to change in case we did.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Lars Jankowfsky is the CTO of Germany-based swoodoo AG.&lt;/b&gt;&lt;/p&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Performance Testing</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/2-Performance-Testing.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/2-guid.html</id>
		<updated>2009-03-06T11:00:00+00:00</updated>
		<content type="html">&lt;p&gt;&lt;b&gt;This is an abstract for a chapter from a book on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/&quot;&gt;Quality Assurance in PHP Projects&lt;/a&gt;.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Incorrect application functionality is a detriment to any project, but poor performance and scalability can often lead to end-user dissatisfaction and exorbitant hardware expenses.&lt;/p&gt;&lt;p&gt;In the case of modern web application, expectations have made it necessary to provide responses within as little as 100 to 500 milliseconds. This puts a tremendous burden on not only achieving excellent performance, but maintaining consistent performance as code changes and new features are added.&lt;/p&gt;&lt;p&gt;We will review a variety of tools that can be used to test performance and scalability.  While the stack will be assumed to be Linux, Apache, MySQL and PHP (LAMP), the basic skills and tools can be applied to a variety of systems (and often the ability to correctly test different system components is itself a valid test case).&lt;/p&gt;&lt;p&gt;An initial emphasis will be on the most basic end-to-end testing of the entire request and response cycle, but later will detail smaller benchmarks and developing custom tool sets once you require more precision. Operating System metrics are also key to ensuring an application's scalability and performance, so tools such as &lt;a href=&quot;http://en.wikipedia.org/wiki/Sar_in_UNIX&quot;&gt;sar&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Strace&quot;&gt;strace&lt;/a&gt;, and &lt;a href=&quot;http://oprofile.sourceforge.net/&quot;&gt;oprofile&lt;/a&gt; will be covered. Because performance testing has unique requirements and challenges we will cover methodologies to correctly implement performance tests, benchmarks and the pitfalls to avoid. These include the short term assurance of accuracy, reproducing results, as well as long term goals and how to balance future expectations, growth, and priorities of an entire product or service.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Brian Shire is Facebook's technical lead for PHP internals and a developer for the Alternative PHP Cache (APC).&lt;/b&gt;&lt;/p&gt;</content>
		<author>
			<name>Brian Shire</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Introduction</title>
		<link href="http://qualityassuranceinphpprojects.com/archives/1-Introduction.html"/>
		<id>http://qualityassuranceinphpprojects.com/archives/1-guid.html</id>
		<updated>2009-03-05T11:00:00+00:00</updated>
		<content type="html">&lt;a href=&quot;http://qualityassuranceinphpprojects.com/pages/authors.html&quot;&gt;Stefan Priebsch&lt;/a&gt; and myself, &lt;a href=&quot;http://qualityassuranceinphpprojects.com/pages/authors.html&quot;&gt;Sebastian Bergmann&lt;/a&gt;, are writing a book on &quot;Quality Assurance in PHP Projects&quot;. The book will be published in &lt;a href=&quot;http://qualityassuranceinphpprojects.com/pages/english_edition.html&quot;&gt;English&lt;/a&gt; and &lt;a href=&quot;http://qualityassuranceinphpprojects.com/pages/german_edition.html&quot;&gt;German&lt;/a&gt; at the same time later this year.&lt;br /&gt;
&lt;br /&gt;
The idea for the book is that Stefan Priebsch and I write the introductory as well as the concluding chapters while other authors contribute case studies for the middle part of the book.&lt;br /&gt;
&lt;br /&gt;
The case study authors will not always agree with each other. In fact, we invite different opinions on how problems are solved to give the readers not &quot;one single truth&quot; but provide different approaches to problems and views on issues.&lt;br /&gt;
&lt;br /&gt;
Our motivation to write this book is simple: there is no such book on the market and from our experience a book such as this is needed. We get questions from our clients all the time: which book can I get for my developers or recommend to potential job applicants as required reading for the topic of web application quality assurance? This book will be the answer to these questions.&lt;br /&gt;
&lt;br /&gt;
The list of case study authors includes contributors to &lt;a href=&quot;http://qualityassuranceinphpprojects.com/categories/Open-Source-Case-Studies&quot;&gt;well-known Open Source projects from the PHP community&lt;/a&gt; as well as developers working on &lt;a href=&quot;http://qualityassuranceinphpprojects.com/categories/Enterprise-Case-Studies&quot;&gt;some of the largest websites built using PHP&lt;/a&gt;, which happen to be some of the Web's most popular sites. Other contributing authors write about &lt;a href=&quot;http://qualityassuranceinphpprojects.com/categories/Practices-and-Tools&quot;&gt;practices and tools&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Over the course of the next weeks, we will introduce each case study author together with the case study he or she is contributing to the book.</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://qualityassuranceinphpprojects.com/</uri>
		</author>
		<source>
			<title type="html">Quality Assurance in PHP Projects</title>
			<link rel="self" href="http://qualityassuranceinphpprojects.com/feeds/index.rss2"/>
			<id>http://qualityassuranceinphpprojects.com/feeds/index.rss2</id>
			<updated>2010-02-25T11:00:03+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Book your holiday in the concentration camp?</title>
		<link href="http://www.frontalaufprall.com/2009/03/03/book-your-holiday-in-the-concentration-camp/"/>
		<id>http://www.frontalaufprall.com/?p=115</id>
		<updated>2009-03-03T12:57:42+00:00</updated>
		<content type="html">&lt;p&gt;Interesting title isn&amp;#8217;t it ? Sounds macabre? It is!&lt;/p&gt;
&lt;p&gt;During my work at &lt;a href=&quot;http://www.swoodoo.com&quot; target=&quot;_blank&quot;&gt;swoodoo.com&lt;/a&gt; (german only, sorry) I accidentially stumbled upon translation issues concerning the city &amp;#8220;Kaunas&amp;#8221; (Lithuania) on other - travel related - webpages.&lt;/p&gt;
&lt;p&gt;The city Kaunas was translated into &amp;#8220;&lt;a href=&quot;http://en.wikipedia.org/wiki/Kaunas_Ghetto&quot; target=&quot;_blank&quot;&gt;KZ Kauen&lt;/a&gt;&amp;#8220;.&lt;/p&gt;
&lt;p&gt;Actually &amp;#8220;KZ&amp;#8221; means &amp;#8220;Konzentrationslager&amp;#8221; == Concentration Camp. And &amp;#8220;Kauen&amp;#8221; is the old &amp;#8220;Nazi&amp;#8221; name for Kaunas. In Kaunas was the largest &lt;a href=&quot;http://www.ushmm.org/museum/exhibit/online/kovno/intro/intro.htm&quot; target=&quot;_blank&quot;&gt;concentration camp in Lithuania&lt;/a&gt; where the Nazis killed around 25.000 people.&lt;/p&gt;
&lt;p&gt;Interested in a hotel in the concentration camp?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;alignnone size-medium wp-image-120&quot; title=&quot;kayak-detail&quot; src=&quot;http://www.frontalaufprall.com/wp-content/uploads/2009/03/kayak-detail-300x212.png&quot; alt=&quot;kayak-detail&quot; width=&quot;300&quot; height=&quot;212&quot; /&gt;&lt;/p&gt;
&lt;p&gt;More over - and this is the reason why I post this under the &amp;#8220;PHP&amp;#8221; flag - I want to show how dangerous it is to copy translations from other websites. Exactly this seemed to have happend - there is a bunch of websites out there who obviously copied from the same source.&lt;/p&gt;
&lt;p&gt;Want a cheap flight into the concentration camp?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;alignnone size-medium wp-image-118&quot; title=&quot;dohop-google&quot; src=&quot;http://www.frontalaufprall.com/wp-content/uploads/2009/03/dohop-google-300x35.png&quot; alt=&quot;dohop-google&quot; width=&quot;300&quot; height=&quot;35&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Or interested how the weather is in the concentration camp ?&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;alignnone size-medium wp-image-121&quot; title=&quot;wettercom&quot; src=&quot;http://www.frontalaufprall.com/wp-content/uploads/2009/03/wettercom-300x226.png&quot; alt=&quot;wettercom&quot; width=&quot;300&quot; height=&quot;226&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And even worse - Adwords booked on the term &amp;#8220;KZ Kauen&amp;#8221;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;alignnone size-full wp-image-116&quot; title=&quot;adword&quot; src=&quot;http://www.frontalaufprall.com/wp-content/uploads/2009/03/adword.png&quot; alt=&quot;adword&quot; width=&quot;214&quot; height=&quot;70&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I doubt that they booked this adword, most likely it is &amp;#8220;Dynamic Keyword Insertion&amp;#8221;&amp;#8230; but nevertheless quite macabre.&lt;/p&gt;
&lt;p&gt;If you are into I18n then you should take translation serious. Quite often translated webpages simply sound silly or funny, but as you can see in this example - sometimes it can be worse.&lt;/p&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<uri>http://www.frontalaufprall.com</uri>
		</author>
		<source>
			<title type="html">Frontalaufprall &#187; PHP related</title>
			<subtitle type="html">PHP, Agile Development und vorallem auch dies und das</subtitle>
			<link rel="self" href="http://www.frontalaufprall.com/category/php/feed/"/>
			<id>http://www.frontalaufprall.com/category/php/feed/</id>
			<updated>2010-03-15T00:00:23+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">phpUnderControl tutorial</title>
		<link href="http://www.manuel-pichler.de/archives/52-phpUnderControl-tutorial.html"/>
		<id>http://www.manuel-pichler.de/archives/52-guid.html</id>
		<updated>2009-02-25T14:40:20+00:00</updated>
		<content type="html">&lt;p&gt;
  Just now I found in Felix's &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2103&amp;entry_id=52&quot; title=&quot;http://felix.phpbelgium.be/blog&quot;&gt;blog&lt;/a&gt; this excellent &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2100&amp;entry_id=52&quot; title=&quot;http://felix.phpbelgium.be/blog/2009/02/07/setting-up-phpundercontrol/&quot;&gt;phpUnderControl tutorial&lt;/a&gt; that comes with useful tips and helping scripts. Because I think it is a really good source to get started with &lt;a href=&quot;http://www.manuel-pichler.de/exit.php?url_id=2101&amp;entry_id=52&quot; title=&quot;http://www.phpundercontrol.org&quot;&gt;phpUnderControl&lt;/a&gt; I will link it here.
&lt;/p&gt;</content>
		<author>
			<name>Manuel Pichler</name>
			<email>nospam@example.com</email>
			<uri>http://www.manuel-pichler.de/</uri>
		</author>
		<source>
			<title type="html">Manuel Pichler - phpundercontrol</title>
			<subtitle type="html">Trust is good, (phpUnder)Control is better.</subtitle>
			<link rel="self" href="http://manuel-pichler.de/feeds/categories/10-phpundercontrol.rss"/>
			<id>http://manuel-pichler.de/feeds/categories/10-phpundercontrol.rss</id>
			<updated>2010-02-01T05:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Fixture Reuse in PHPUnit 3.4</title>
		<link href="http://sebastian-bergmann.de/archives/848-Fixture-Reuse-in-PHPUnit-3.4.html"/>
		<id>http://sebastian-bergmann.de/archives/848-guid.html</id>
		<updated>2009-02-25T10:25:00+00:00</updated>
		<content type="html">&lt;p&gt;As mentioned earlier, &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit 3.4&lt;/a&gt; adds support for &lt;a href=&quot;http://sebastian-bergmann.de/archives/826-Test-Dependencies-in-PHPUnit-3.4.html&quot;&gt;Test Dependencies&lt;/a&gt; as introduced by &lt;a href=&quot;http://smallwiki.unibe.ch/adriankuhn/&quot;&gt;Kuhn&lt;/a&gt; et. al. in &lt;a href=&quot;http://www.iam.unibe.ch/~scg/Archive/Papers/Kuhn08aJExample.pdf&quot;&gt;JExample: Exploiting Dependencies Between Tests to Improve Defect Localization&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Today I implemented fixture reuse based on test dependency information:&lt;/p&gt;&lt;dl&gt;&lt;dd&gt;&lt;pre class=&quot;programlisting&quot;&gt;&lt;code&gt;&lt;span class=&quot;default&quot;&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;StackTest&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;PHPUnit_Framework_TestCase&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testPush&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$stack&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$stack&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;array_push&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$stack&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'foo'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'foo'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$stack&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$stack&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$stack&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$stack&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;comment&quot;&gt;/**&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*&amp;#160;@depends&amp;#160;testPush&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*/&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;testPop&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$stack&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string&quot;&gt;'foo'&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;array_pop&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$stack&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;default&quot;&gt;$stack&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;keyword&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;default&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/dd&gt;&lt;/dl&gt;&lt;p&gt;Just like &lt;a href=&quot;http://smallwiki.unibe.ch/jexample&quot;&gt;JExample&lt;/a&gt;, PHPUnit 3.4 introduces producer-consumer relationships to unit-testing.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A producer is a test method that yields its unit under test as return value.&lt;/li&gt;&lt;li&gt;A consumer is a test method that depends on one or more producers and their return values.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;PHPUnit 3.4 skips any test method whose producer has failed and the return value of a producer is injected into its consumers.&lt;/p&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit 3.3.14</title>
		<link href="http://sebastian-bergmann.de/archives/845-PHPUnit-3.3.14.html"/>
		<id>http://sebastian-bergmann.de/archives/845-guid.html</id>
		<updated>2009-02-06T21:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/692&quot; title=&quot;defect: phpunit works related on order of bootstrap and skeleton-test paramenters (closed: fixed)&quot;&gt;#692&lt;/a&gt;: PHPUnit works related on order of &lt;tt&gt;--bootstrap&lt;/tt&gt; and &lt;tt&gt;--skeleton-test&lt;/tt&gt; switches. &lt;a href=&quot;http://www.phpunit.de/changeset/4581&quot; title=&quot;- Merge [4579].&quot;&gt;[4581]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/697&quot; title=&quot;defect: PHPUnit incorrectly instantiates Selenium tests with multiple browsers (closed: fixed)&quot;&gt;#697&lt;/a&gt;: PHPUnit incorrectly instantiates &lt;tt&gt;SeleniumTestCase&lt;/tt&gt; tests with multiple browsers. &lt;a href=&quot;http://www.phpunit.de/changeset/4608&quot; title=&quot;- Merge [4606].&quot;&gt;[4608]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/702&quot; title=&quot;defect: Incorrect text in PHPUnit_Framework_ComparisonFailure_Array (closed: fixed)&quot;&gt;#702&lt;/a&gt;: Incorrect text in &lt;tt&gt;PHPUnit_Framework_ComparisonFailure_Array&lt;/tt&gt;. &lt;a href=&quot;http://www.phpunit.de/changeset/4613&quot; title=&quot;- Merge [4611].&quot;&gt;[4613]&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">YAML Now Supported by PHPUnit Database Extension</title>
		<link href="http://www.ds-o.com/archives/79-YAML-Now-Supported-by-PHPUnit-Database-Extension.html"/>
		<id>http://www.ds-o.com/archives/79-guid.html</id>
		<updated>2009-02-01T18:22:13+00:00</updated>
		<content type="html">&lt;p&gt;I have now just committed &lt;a href=&quot;http://www.ds-o.com/exit.php?url_id=246&amp;entry_id=79&quot; title=&quot;http://yaml.org/&quot;&gt;YAML&lt;/a&gt; data sets to the Database Extension for &lt;a href=&quot;http://www.ds-o.com/exit.php?url_id=247&amp;entry_id=79&quot; title=&quot;http://www.phpun.it&quot;&gt;PHPUnit&lt;/a&gt;. 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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;div&gt;&lt;br /&gt;
table1:&lt;br /&gt;
&amp;#160; -&lt;br /&gt;
&amp;#160; &amp;#160; table1_id: 1&lt;br /&gt;
&amp;#160; &amp;#160; columnName1: &amp;quot;tgfahgasdf&amp;quot;&lt;br /&gt;
&amp;#160; &amp;#160; columnName2: 200&lt;br /&gt;
&amp;#160; &amp;#160; columnName3: 34.64&lt;br /&gt;
&amp;#160; &amp;#160; columnName4: yghkf;a&amp;#160; hahfg8ja h;&lt;br /&gt;
table2:&lt;br /&gt;
&amp;#160; -&lt;br /&gt;
&amp;#160; &amp;#160; table2_id: 1&lt;br /&gt;
&amp;#160; &amp;#160; column5: fhah&lt;br /&gt;
&amp;#160; &amp;#160; column6: 456&lt;br /&gt;
&amp;#160; &amp;#160; column7: 46.5&lt;br /&gt;
&amp;#160; &amp;#160; column8: &amp;quot;fsdb, ghfdas&amp;quot;&lt;br /&gt;
&amp;#160; -&lt;br /&gt;
&amp;#160; &amp;#160; table2_id: 3&lt;br /&gt;
&amp;#160; &amp;#160; column5: ajsdlkfguitah&lt;br /&gt;
&amp;#160; &amp;#160; column6: 654&lt;br /&gt;
&amp;#160; &amp;#160; column7: blah&lt;br /&gt;
&amp;#160; &amp;#160; column8: |-&lt;br /&gt;
&amp;#160; &amp;#160; &amp;#160; thesethasdl&lt;br /&gt;
&amp;#160; &amp;#160; &amp;#160; asdflkjsadf asdfsadfhl &amp;quot;adsf, halsdf&amp;quot; sadfhlasdf&lt;br /&gt;
&lt;/div&gt;

&lt;p&gt;The biggest issue I had was figuring out how YAML dealt with trailing line breaks. It appears that '|-' did the trick. It will strip the final line break. Another thing to take note is that indention is important. It doesn'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.)&lt;/p&gt;

&lt;p&gt;This was committed to the trunk of PHPUnit and I anticipate Sebastian will be merging it back into 3.4 shortly.&lt;/p&gt;</content>
		<author>
			<name>Mike Lively</name>
			<email>nospam@example.com</email>
			<uri>http://www.ds-o.com/</uri>
		</author>
		<source>
			<title type="html">Digital Sandwich - PHP Testing</title>
			<subtitle type="html">PHP, Music, and other stuff</subtitle>
			<link rel="self" href="http://www.ds-o.com/feeds/categories/9-PHP-Testing.rss"/>
			<id>http://www.ds-o.com/feeds/categories/9-PHP-Testing.rss</id>
			<updated>2009-03-29T09:23:46+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Improved PHPUnit Filters</title>
		<link href="http://www.ds-o.com/archives/78-Improved-PHPUnit-Filters.html"/>
		<id>http://www.ds-o.com/archives/78-guid.html</id>
		<updated>2009-02-01T04:54:28+00:00</updated>
		<content type="html">&lt;p&gt;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 &lt;a href=&quot;http://www.ds-o.com/exit.php?url_id=237&amp;entry_id=78&quot; title=&quot;http://www.phpunit.de/ticket/526&quot;&gt;ticket #526&lt;/a&gt;. Essentially I added the ability to do both white list and black list filtering.
&lt;/p&gt;

&lt;p&gt;For instance, if you wanted to specify an include filter you can do the following:&lt;/p&gt;

&lt;div class=&quot;php&quot;&gt;&lt;br /&gt;&lt;span&gt;&amp;lt;?php&lt;/span&gt; &lt;br /&gt;&lt;span&gt;//... &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;$filteredDataSet&lt;/span&gt; = &lt;span&gt;new&lt;/span&gt; PHPUnit_Extensions_Database_DataSet_DataSetFilter&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;$dataSet&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;$filteredDataSet&lt;/span&gt;-&amp;gt;&lt;span&gt;addIncludeTables&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'table1'&lt;/span&gt;, &lt;span&gt;'table3'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;; &lt;br /&gt;&lt;span&gt;$filteredDataSet&lt;/span&gt;-&amp;gt;&lt;span&gt;setIncludeColumnsForTable&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'table1'&lt;/span&gt;, &lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'column1'&lt;/span&gt;, &lt;span&gt;'column2'&lt;/span&gt;, &lt;span&gt;'column3'&lt;/span&gt;, &lt;span&gt;'column4'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;; &lt;br /&gt;&lt;span&gt;$filteredDataSet&lt;/span&gt;-&amp;gt;&lt;span&gt;setIncludeColumnsForTable&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'table3'&lt;/span&gt;, &lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'column9'&lt;/span&gt;, &lt;span&gt;'column10'&lt;/span&gt;, &lt;span&gt;'column11'&lt;/span&gt;, &lt;span&gt;'column12'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;//... &lt;/span&gt;&lt;br /&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;/div&gt;

&lt;p&gt;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.
&lt;/p&gt;

&lt;p&gt;So, for exclude filters, instead of specifying them in the constructor, the new method will be:&lt;/p&gt;

&lt;div class=&quot;php&quot;&gt;&lt;br /&gt;&lt;span&gt;&amp;lt;?php&lt;/span&gt; &lt;br /&gt;&lt;span&gt;//...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;$filteredDataSet&lt;/span&gt; = &lt;span&gt;new&lt;/span&gt; PHPUnit_Extensions_Database_DataSet_DataSetFilter&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;$dataSet&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;$filteredDataSet&lt;/span&gt;-&amp;gt;&lt;span&gt;addExcludeTables&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'table2'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;; &lt;br /&gt;&lt;span&gt;$filteredDataSet&lt;/span&gt;-&amp;gt;&lt;span&gt;setExcludeColumnsForTable&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'table1'&lt;/span&gt;, &lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'table1_id'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;; &lt;br /&gt;&lt;span&gt;$filteredDataSet&lt;/span&gt;-&amp;gt;&lt;span&gt;setExcludeColumnsForTable&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'table3'&lt;/span&gt;, &lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'table3_id'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;//... &lt;/span&gt;&lt;br /&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;/div&gt;

&lt;p&gt;While you can't mix include and exclude filters for tables (wouldn't make sense right now) you CAN do this for table columns of separate tables:&lt;/p&gt;

&lt;div class=&quot;php&quot;&gt;&lt;br /&gt;&lt;span&gt;&amp;lt;?php&lt;/span&gt; &lt;br /&gt;&lt;span&gt;//...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;$filteredDataSet&lt;/span&gt; = &lt;span&gt;new&lt;/span&gt; PHPUnit_Extensions_Database_DataSet_DataSetFilter&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;$dataSet&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;$filteredDataSet&lt;/span&gt;-&amp;gt;&lt;span&gt;addIncludeTables&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'table1'&lt;/span&gt;, &lt;span&gt;'table3'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;; &lt;br /&gt;&lt;span&gt;$filteredDataSet&lt;/span&gt;-&amp;gt;&lt;span&gt;setExcludeColumnsForTable&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'table1'&lt;/span&gt;, &lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'table1_id'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;; &lt;br /&gt;&lt;span&gt;$filteredDataSet&lt;/span&gt;-&amp;gt;&lt;span&gt;setIncludeColumnsForTable&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'table3'&lt;/span&gt;, &lt;a href=&quot;http://www.php.net/array&quot;&gt;&lt;span&gt;array&lt;/span&gt;&lt;/a&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'column9'&lt;/span&gt;, &lt;span&gt;'column10'&lt;/span&gt;, &lt;span&gt;'column11'&lt;/span&gt;, &lt;span&gt;'column12'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;//... &lt;/span&gt;&lt;br /&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;#160;&lt;/div&gt;

&lt;p&gt;Some future features I plan on adding include, global column includes/excludes and wild cards. Anyhow, hope this is useful for someone.&lt;/p&gt;</content>
		<author>
			<name>Mike Lively</name>
			<email>nospam@example.com</email>
			<uri>http://www.ds-o.com/</uri>
		</author>
		<source>
			<title type="html">Digital Sandwich - PHP Testing</title>
			<subtitle type="html">PHP, Music, and other stuff</subtitle>
			<link rel="self" href="http://www.ds-o.com/feeds/categories/9-PHP-Testing.rss"/>
			<id>http://www.ds-o.com/feeds/categories/9-PHP-Testing.rss</id>
			<updated>2009-03-29T09:23:46+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit 3.3.11</title>
		<link href="http://sebastian-bergmann.de/archives/844-PHPUnit-3.3.11.html"/>
		<id>http://sebastian-bergmann.de/archives/844-guid.html</id>
		<updated>2009-01-25T16:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/670&quot; title=&quot;defect: XML configuration file ignored when executing single test case. (closed: fixed)&quot;&gt;#670&lt;/a&gt;: XML configuration file ignored when executing single test case. &lt;a href=&quot;http://www.phpunit.de/changeset/4538&quot; title=&quot;- Merge [4536].&quot;&gt;[4538]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/677&quot; title=&quot;defect: PHPUnit_Extensions_SeleniumTestCase::__construct() does not forward all ... (closed: fixed)&quot;&gt;#677&lt;/a&gt;: &lt;tt&gt;PHPUnit_Extensions_SeleniumTestCase::__construct()&lt;/tt&gt; does not forward all arguments. &lt;a href=&quot;http://www.phpunit.de/changeset/4507&quot; title=&quot;- Merge [4505].&quot;&gt;[4507]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/678&quot; title=&quot;defect: Implementation of PHPUNIT_SELENIUM_TEST_ID cookie deletion is wrong. (closed: fixed)&quot;&gt;#678&lt;/a&gt;: Implementation of &lt;tt&gt;PHPUNIT_SELENIUM_TEST_ID&lt;/tt&gt; cookie deletion is wrong. &lt;a href=&quot;http://www.phpunit.de/changeset/4519&quot; title=&quot;- Merge [4517].&quot;&gt;[4519]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/683&quot; title=&quot;defect: make code coverage report valid html (closed: fixed)&quot;&gt;#683&lt;/a&gt;: Make code coverage report valid HTML. &lt;a href=&quot;http://www.phpunit.de/changeset/4548&quot; title=&quot;- Merge [4546].&quot;&gt;[4548]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/684&quot; title=&quot;defect: Unable to find test class when no test methods exists (closed: fixed)&quot;&gt;#684&lt;/a&gt;: Unable to find test class when no test method exists. &lt;a href=&quot;http://www.phpunit.de/changeset/4553&quot; title=&quot;- Merge [4549], [4550], and [4551].&quot;&gt;[4553]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed an &lt;tt&gt;E_NOTICE&lt;/tt&gt; on Windows because &lt;tt&gt;LC_MESSAGES&lt;/tt&gt; is not defined. &lt;a href=&quot;http://www.phpunit.de/changeset/4498&quot; title=&quot;- Merge [4496].&quot;&gt;[4498]&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">The Cost of Test Isolation - Follow-Up</title>
		<link href="http://sebastian-bergmann.de/archives/843-The-Cost-of-Test-Isolation-Follow-Up.html"/>
		<id>http://sebastian-bergmann.de/archives/843-guid.html</id>
		<updated>2009-01-18T13:35:00+00:00</updated>
		<content type="html">&lt;p&gt;This is a follow-up to &quot;&lt;a href=&quot;http://sebastian-bergmann.de/archives/830-The-Cost-of-Test-Isolation-and-other-PHPUnit-Features.html&quot;&gt;The Cost of Test Isolation (and other PHPUnit Features)&lt;/a&gt;&quot;.&lt;/p&gt;&lt;p&gt;Since the previous posting, I have added a &lt;a href=&quot;http://www.phpunit.de/manual/3.4/en/fixtures.html#fixtures.global-state&quot;&gt;backup/restore mechanism for static attributes of classes&lt;/a&gt; to &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt;. This is yet another feature of PHPUnit that makes the testing of code that uses global state (which includes, but is not limited to, &lt;a href=&quot;http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html&quot;&gt;global and superglobal variables&lt;/a&gt; as well as static attributes of classes) easier.&lt;/p&gt;&lt;p&gt;The following profiling graph illustrates the performance penalty incurred by this feature on the test execution.&lt;/p&gt;&lt;a href=&quot;http://www.flickr.com/photos/sebastian_bergmann/3206494878/&quot; title=&quot;Profiling PHPUnit with Xdebug by Sebastian Bergmann, on Flickr&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3093/3206494878_106ce9e924_m.jpg&quot; width=&quot;177&quot; height=&quot;240&quot; alt=&quot;Profiling PHPUnit with Xdebug&quot; /&gt;&lt;/a&gt;&lt;p&gt;The following profiling graph was generated for an execution of PHPUnit with the &lt;code&gt;--no-syntax-check --no-globals-backup --no-static-backup&lt;/code&gt; switches that disable these features (and also the syntac check of test code).&lt;/p&gt;&lt;a href=&quot;http://www.flickr.com/photos/sebastian_bergmann/3206494876/&quot; title=&quot;Profiling PHPUnit with Xdebug by Sebastian Bergmann, on Flickr&quot;&gt;&lt;img src=&quot;http://farm4.static.flickr.com/3457/3206494876_d6332400fe_m.jpg&quot; width=&quot;240&quot; height=&quot;205&quot; alt=&quot;Profiling PHPUnit with Xdebug&quot; /&gt;&lt;/a&gt;&lt;p&gt;My recommendation is: disable the backup/restore mechanism of globals and static attributes of classes. Not only because this greatly reduces the time required to run the tests. It also exposes tests, and thus the tested code, that interacts with global state. If, and only if, this interaction with global state cannot be avoided you can select the tests for which the backup/restore mechanism(s) should be enabled in a fine-grained way.&lt;/p&gt;&lt;p&gt;If you are interested in the problems associated with code that interacts with global state, especially with regard to testing it, join me for my &quot;&lt;a href=&quot;http://sebastian-bergmann.de/archives/840-Speaking-at-phptek-2009.html&quot;&gt;Untestable Code&lt;/a&gt; session at the &lt;a href=&quot;http://tek.mtacon.com/&quot;&gt;php|tek 2009&lt;/a&gt; conference in Chicago, IL, US in May.&lt;/p&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit 3.3.10</title>
		<link href="http://sebastian-bergmann.de/archives/842-PHPUnit-3.3.10.html"/>
		<id>http://sebastian-bergmann.de/archives/842-guid.html</id>
		<updated>2009-01-13T16:45:00+00:00</updated>
		<content type="html">&lt;ul&gt;&lt;li&gt;Implemented &lt;a href=&quot;http://www.phpunit.de/ticket/671&quot; title=&quot;enhancement: Allow constants as values for php.ini settings set via the XML ... (closed: fixed)&quot;&gt;#671&lt;/a&gt;: Allow constants as values for &lt;tt&gt;php.ini&lt;/tt&gt; settings set via the XML configuration file. &lt;a href=&quot;http://www.phpunit.de/changeset/4455&quot; title=&quot;- Merge [4453].&quot;&gt;[4455]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/667&quot; title=&quot;defect: PHPUnit_Framework_Assert::getStaticAttribute() does not work for ... (closed: fixed)&quot;&gt;#667&lt;/a&gt;: &lt;tt&gt;PHPUnit_Framework_Assert::getStaticAttribute()&lt;/tt&gt; does not work for properties with &lt;tt&gt;NULL&lt;/tt&gt; value. &lt;a href=&quot;http://www.phpunit.de/changeset/4432&quot; title=&quot;- Merge [4430].&quot;&gt;[4432]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/668&quot; title=&quot;defect: Directory separator needs to be escaped in YUI panel data (closed: fixed)&quot;&gt;#668&lt;/a&gt;: Directory separator needs to be escaped in YUI panel data. &lt;a href=&quot;http://www.phpunit.de/changeset/4447&quot; title=&quot;- Merge [4445].&quot;&gt;[4447]&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Upcoming Talks</title>
		<link href="http://www.frontalaufprall.com/2009/01/13/upcoming-talks/"/>
		<id>http://www.frontalaufprall.com/?p=111</id>
		<updated>2009-01-13T07:55:39+00:00</updated>
		<content type="html">&lt;p&gt;This year will be very interesting as I will present two talks in Rome, Italy at the &lt;a href=&quot;http://www.phpcon.it&quot; target=&quot;_blank&quot;&gt;PHP Conferenc&lt;/a&gt;e. As this will be my first time in Rome I am really looking forward to visit this fabulous place.&lt;/p&gt;
&lt;p&gt;My Talks will be:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Monitor your Business&lt;/p&gt;
&lt;p&gt;The most important thing happening in your website is the business process. So why should you monitor your database and your webserver only when your business is failing? Monitoring is not only about hardware and databases - it&amp;#8217;s also about the internals of your application. Learn how to monitor your business using PHP and how to create nice, good looking management compatible graphs.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;This talk will be a highly improved version of the talk I have held at the &lt;a href=&quot;http://it-republik.de/php/phpconference/&quot; target=&quot;_blank&quot;&gt;IPC 2008&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And something new, and (I hope) quite interesting:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Why Architecture in Web Development matters&lt;/p&gt;
&lt;p&gt;Choosing the right software architecture for your project is very important. Besides the framework decision there are many other key issues you need to take into account and which have an impact on such things like maintainability, scalability and also the frequency of possible deployments. In this session you will to learn why you have to remove Co-dependency in your source code, which patterns there are for successful scaling and how the choosen framework influences your architecture.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Hope to see you in italy &lt;img src=&quot;http://www.frontalaufprall.com/wp-includes/images/smilies/icon_wink.gif&quot; alt=&quot;;)&quot; class=&quot;wp-smiley&quot; /&gt; &lt;/p&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<uri>http://www.frontalaufprall.com</uri>
		</author>
		<source>
			<title type="html">Frontalaufprall &#187; PHP related</title>
			<subtitle type="html">PHP, Agile Development und vorallem auch dies und das</subtitle>
			<link rel="self" href="http://www.frontalaufprall.com/category/php/feed/"/>
			<id>http://www.frontalaufprall.com/category/php/feed/</id>
			<updated>2010-03-15T00:00:23+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Outsourcing and Quality&#8230;</title>
		<link href="http://www.frontalaufprall.com/2009/01/11/outsourcing-and-quality/"/>
		<id>http://www.frontalaufprall.com/?p=110</id>
		<updated>2009-01-11T09:04:17+00:00</updated>
		<content type="html">&lt;p&gt;Yesterday night I&amp;#8217;ve received an interesting comment on my &lt;a href=&quot;http://www.frontalaufprall.com/2009/01/08/phpindia/&quot; target=&quot;_self&quot;&gt;PHP@INDIA&lt;/a&gt; posting. After reading I&amp;#8217;ve decided that this deserves a posting to answer it thoroughly.&lt;/p&gt;
&lt;p&gt;The comment was&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The poster who made this statement doesn&#8217;t explain to you that India-based workers can only speak about 60% english.&lt;/p&gt;
&lt;p&gt;he doesn&#8217;t explain that these same developers use BEGINNER LEVEL coding techniques that render your site open to almost the most grade-school level of attacks.&lt;/p&gt;
&lt;p&gt;he doesn&#8217;t explain to you that these same developers don&#8217;t give a damn about you, or your project.&lt;/p&gt;
&lt;p&gt;he doesn&#8217;t explain to you that their answers to questions are from monitors on their screen, and should you have an advanced-level technical question they are NOT going to be able to answer for you.&lt;/p&gt;
&lt;p&gt;And he also didn&#8217;t explain that you GET what you PAY for. You pay for garbage in India, expect garbage as a product. You pay good in America for a product, expect the best as a product.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The commentor is right in his statements. Actually talking about Quality in outsourcing you need to take care that the quality is good enough for you. It would be simply very dumb to rely on any developer - check it personally! I&amp;#8217;ve made the same experience 10 years ago like my anonymous commentor, but I had to understand that things changed and that it is possible now to get better quality. But as always - you need the right partner.&lt;/p&gt;
&lt;p&gt;After reading my posting again I&amp;#8217;ve realized that I need to clearify a few things. Outsourcing (in PHP area!) is never about saving money. Having good people inhouse or around the corner will help your project a lot. Outsourcing is about scaling. If you do have any tasks which need to be scaled, like developing the same stuff again and again, editing pictures, running any process against something which need to be repeateded over and over then you should think about offshoring.&lt;/p&gt;
&lt;p&gt;I state that it&amp;#8217;s very difficult to scale your team from 5 to 15 inhouse fast - and this is possible in india. Simply because there are many indians.&lt;/p&gt;
&lt;p&gt;A few rules need to be applied to choose the right partner:&lt;/p&gt;
&lt;p&gt;- Do never ever give your core technology to any outsourcer somewhere on this planet. You need to have full control over your technology. Otherwise the risk of beeing ripped off is very high.&lt;/p&gt;
&lt;p&gt;- Choose your partner thorougly. Check the references and call them to doublecheck.&lt;/p&gt;
&lt;p&gt;- Be aware of your expectations. You will need a few months before the project will run by itself.&lt;/p&gt;
&lt;p&gt;- if you do not put in energy, knowhow and your personal sweat it won&amp;#8217;t work.&lt;/p&gt;
&lt;p&gt;Follow these rules and your outsourcing project will be successful.&lt;/p&gt;
&lt;p&gt;To come to an end - yes, also in india you get what you pay for. This is valid anywhere on the planet. Pay your developers well and you will get good quality. And for sure you can not judge over all people in a country - there are good and bad developers all over the planet. Even though it is hard to believe - just beeing american doesn&amp;#8217;t make you a good developer - and vice versa - beeing indian doesn&amp;#8217;t make you a bad developer.&lt;/p&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<uri>http://www.frontalaufprall.com</uri>
		</author>
		<source>
			<title type="html">Frontalaufprall &#187; PHP related</title>
			<subtitle type="html">PHP, Agile Development und vorallem auch dies und das</subtitle>
			<link rel="self" href="http://www.frontalaufprall.com/category/php/feed/"/>
			<id>http://www.frontalaufprall.com/category/php/feed/</id>
			<updated>2010-03-15T00:00:23+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHP@INDIA ?</title>
		<link href="http://www.frontalaufprall.com/2009/01/08/phpindia/"/>
		<id>http://www.frontalaufprall.com/?p=109</id>
		<updated>2009-01-08T13:20:13+00:00</updated>
		<content type="html">&lt;p&gt;Did you ever wonder if these Millions of Indian developer we often read about are capabale of doing good in PHP? I did. And I &lt;a href=&quot;http://www.frontalaufprall.com/2008/06/22/incredible-india-a-php-adventure-part1/&quot; target=&quot;_blank&quot;&gt;tried&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Back in my past (*cough* - hitting 40 soon&amp;#8230;) I&amp;#8217;ve outsourced parts of my jobs to many countries, starting with a company in Prague/Czech Republic together with my friend &lt;a href=&quot;http://browsing.justdiscourse.com/&quot; target=&quot;_blank&quot;&gt;Matthew&lt;/a&gt;, and moving later on to lithuania where I still run (together with my mate wolfgang) a development office with a total of 60 developers, coding for various projects like &lt;a href=&quot;http://www.swoodoo.com&quot; target=&quot;_blank&quot;&gt;swoodoo&lt;/a&gt; or &lt;a href=&quot;http://www.oxid-esales.com&quot; target=&quot;_blank&quot;&gt;oxid&lt;/a&gt;.&lt;br /&gt;
During these nearly 25 years I did work for sure in a few projects where coding was outsourced to india. My experience in the past was not really good. The classical project in india was:&lt;/p&gt;
&lt;p&gt;- huge&lt;br /&gt;
- really huge&lt;br /&gt;
- f.. huge&lt;/p&gt;
&lt;p&gt;did I mention huge?&lt;/p&gt;
&lt;p&gt;Why is that so? Well - the average indian developer is (was!) teached to work as some sort of coding-ant. Don&amp;#8217;t think, just do what you gotta do (&lt;a href=&quot;http://www.ew.com/ew/article/0,,272930,00.html&quot; target=&quot;_blank&quot;&gt;futurama&lt;/a&gt;). Thus this ended in a culture where you need to write a very detailed spec ( thousands of pages) and hand this over to your &amp;#8220;ant&amp;#8221; farm where 500-1000 developers code what you told them todo. Still you need to check personally the quality as (in the past!) the indian culture does not support being honest in case of problems as this is considered rude. Ah - being rude&amp;#8230; tell me.. the ones out there who had the pleasure&amp;#8230; to meet me in person know that I am a really honest person thus it is very easy that myself is been taken as rude&amp;#8230;.&lt;/p&gt;
&lt;p&gt;So this was the past - 12 years ago. In 2008 I&amp;#8217;ve started &lt;a href=&quot;http://www.frontalaufprall.com/2008/06/22/incredible-india-a-php-adventure-part1/&quot; target=&quot;_blank&quot;&gt;a second try&lt;/a&gt; - and guess what ? It worked! After investigating the right partner via my personal network I&amp;#8217;ve started to work with &lt;a href=&quot;http://www.anantsol.com/&quot; target=&quot;_blank&quot;&gt;Anantara&lt;/a&gt;. A small company, with very bright minds in management, reliable and trustworthy. Nothing what you can expect anywhere on the planet.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.anantsol.com/&quot; target=&quot;_blank&quot;&gt;Anantara&lt;/a&gt; was working in the usual areas - Java and .NET but not very much in PHP. So I helped them a bit to kickstart a fresh PHP team - and they kept their promises and delivered a good working team. To my pleasure they realized that the PHP area is a very interesting market to them, so they decided to put a lot of energy in this area - sic! Times are really changing, especially now when we talk about the crisis - it matters what you pay for your software, and PHP is simply a lot of cheaper (aka faster) developed compared to .NET and java.&lt;/p&gt;
&lt;p&gt;Don&amp;#8217;t get me wrong - outsourcing is always difficult and by far less efficient compared to in-house developers. You always have to bridge a cultural/business gap which is most likely there. You can&amp;#8217;t expect that some people anywhere on the planet earth understand your business needs without teaching them thoroughly.&lt;/p&gt;
&lt;p&gt;But - in the past I had much worse experiences - and now I&amp;#8217;ve really enjoyed to work with &lt;a href=&quot;http://www.anantsol.com/&quot; target=&quot;_blank&quot;&gt;Anantara&lt;/a&gt; the last year. Our project stopped now, as it ended succesfully, but I am definitly looking forward to work with these guys in future again. From a PHP skill level I would estimate that there is average know how - which is better than many code I&amp;#8217;ve seen in the last years developed in germany. Needless to say that they do agile development - what else&amp;#8230;;)&lt;/p&gt;
&lt;p&gt;So - if you are interested in contacting them or you do have any other question concerning outsourcing - feel free to contact me. I&amp;#8217;ve decided to support &lt;a href=&quot;http://www.anantsol.com/&quot; target=&quot;_blank&quot;&gt;Anantara&lt;/a&gt; a bit as I really do like them - and no - I am not paid, nor am I a shareholder there. Most likely they will pay me a beer (or two&amp;#8230;) &lt;img src=&quot;http://www.frontalaufprall.com/wp-includes/images/smilies/icon_smile.gif&quot; alt=&quot;:)&quot; class=&quot;wp-smiley&quot; /&gt; &lt;/p&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<uri>http://www.frontalaufprall.com</uri>
		</author>
		<source>
			<title type="html">Frontalaufprall &#187; PHP related</title>
			<subtitle type="html">PHP, Agile Development und vorallem auch dies und das</subtitle>
			<link rel="self" href="http://www.frontalaufprall.com/category/php/feed/"/>
			<id>http://www.frontalaufprall.com/category/php/feed/</id>
			<updated>2010-03-15T00:00:23+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">7 things&#8230;.</title>
		<link href="http://www.frontalaufprall.com/2009/01/06/7-things/"/>
		<id>http://www.frontalaufprall.com/?p=108</id>
		<updated>2009-01-06T09:20:41+00:00</updated>
		<content type="html">&lt;p&gt;Already a few days ago I got tagged by &lt;a href=&quot;http://www.manuel-pichler.de/archives/49-Seven-Things-Tagged-by-Kore-Nordmann.html&quot; target=&quot;_blank&quot;&gt;Manuel Pichler&lt;/a&gt; and &lt;a href=&quot;http://100days.de/serendipity/archives/71-7-things-about-me-Tagged.html&quot; target=&quot;_blank&quot;&gt;Gaylord Aulke&lt;/a&gt;. I could not post as I was really sick the last two weeks. Today is the first day where I see light at the end of the tunnel and I feel good enough to answer the questions.&lt;/p&gt;
&lt;p&gt;So you really want to know seven things about me ? Well - you asked for it &lt;img src=&quot;http://www.frontalaufprall.com/wp-includes/images/smilies/icon_smile.gif&quot; alt=&quot;:)&quot; class=&quot;wp-smiley&quot; /&gt; &lt;/p&gt;
&lt;p&gt;1. I earned my first money by creating a blackmarket in secondary school for sexual explicit material, which I bought cheap and sold expensive. This was one of the reasons I had to leave this school.&lt;/p&gt;
&lt;p&gt;2. My first love was named Commodore 64. I teached myself Assembler and started to rip off music from games, creating my own demos.&lt;/p&gt;
&lt;p&gt;3. My holidays are usually spent in croatia as my beloved wife was born there.&lt;/p&gt;
&lt;p&gt;4. I work with a bunch of developers in lithuania, and hey - these guys (and girls!) are really good.&lt;/p&gt;
&lt;p&gt;5. Recently I donated my book collection of &amp;gt; 2500 science fiction and fantasy books to a shop where handicapped sell the books to life from that.&lt;/p&gt;
&lt;p&gt;6. Although I was born in bavaria my limit are 3 litres of beer, after that I am really really drunk.&lt;/p&gt;
&lt;p&gt;7. I can&amp;#8217;t stand cold weather - I feel well at an average of 26+ degrees. Oh, do you remember 4. ? In .lt the winters are really really REALLY cold and I hate it.&lt;/p&gt;
&lt;p&gt;So - now my turn. Not so easy. I think nearly everybody who I know was already tagged, therefore - sorry about that - I need to tag a bunch of german people who I think are not yet tagged by this meme.&lt;/p&gt;
&lt;p&gt;Here we go:&lt;/p&gt;
&lt;p&gt;1. &lt;a href=&quot;http://www.phphatesme.com/&quot; target=&quot;_blank&quot;&gt;Nils Langner &lt;/a&gt;for teaching PHP &lt;img src=&quot;http://www.frontalaufprall.com/wp-includes/images/smilies/icon_wink.gif&quot; alt=&quot;;)&quot; class=&quot;wp-smiley&quot; /&gt;&lt;br /&gt;
2. &lt;a href=&quot;http://devblog.phpmyfaq.de/&quot; target=&quot;_blank&quot;&gt;Thorsten Rinne &lt;/a&gt;just to remember him that he still ows me a self cooked thai menu.&lt;br /&gt;
3. &lt;a href=&quot;http://blog.egolab.de/&quot; target=&quot;_blank&quot;&gt;Xenjo&lt;/a&gt; because I am curious what he would write&amp;#8230;.&lt;br /&gt;
4. &lt;a href=&quot;http://www.ralfeggert.de/&quot; target=&quot;_blank&quot;&gt;Ralf Eggert&lt;/a&gt; to support his upcoming Zend Framework book (in german only)&lt;br /&gt;
5. &lt;a href=&quot;http://www.christopher-kunz.de/&quot; target=&quot;_blank&quot;&gt;Christopher Kunz &lt;/a&gt;who runs partly my servers for &lt;a href=&quot;http://www.swoodoo.com&quot; target=&quot;_blank&quot;&gt;swoodoo&lt;/a&gt; and takes care about themeven from holiday. Thanks Chris !&lt;br /&gt;
6. &lt;a href=&quot;http://tomas.liubinas.com/lt+en/&quot; target=&quot;_blank&quot;&gt;Tomas Liubinas &lt;/a&gt;one of the .lt developers I mentioned and actually he was part of the team who won in &lt;a href=&quot;http://www.plat-forms.org/&quot; target=&quot;_blank&quot;&gt;plat-forms&lt;/a&gt; contest.&lt;br /&gt;
7. &lt;a href=&quot;http://www.maxhorvath.com/&quot; target=&quot;_blank&quot;&gt;Max Horvath&lt;/a&gt; for&amp;#8230; hmm&amp;#8230; I still wait for the pics &lt;img src=&quot;http://www.frontalaufprall.com/wp-includes/images/smilies/icon_wink.gif&quot; alt=&quot;;)&quot; class=&quot;wp-smiley&quot; /&gt; &lt;/p&gt;
&lt;p&gt;These are the rules apparently:&lt;/p&gt;
&lt;p&gt;Link your original tagger(s), and list these rules on your blog.&lt;br /&gt;
Share seven facts about yourself in the post - some random, some weird.&lt;br /&gt;
Tag seven people at the end of your post by leaving their names and the links to their blogs.&lt;br /&gt;
Let them know they&amp;#8217;ve been tagged by leaving a comment on their blogs and/or Twitter.&lt;/p&gt;</content>
		<author>
			<name>Lars Jankowfsky</name>
			<uri>http://www.frontalaufprall.com</uri>
		</author>
		<source>
			<title type="html">Frontalaufprall &#187; PHP related</title>
			<subtitle type="html">PHP, Agile Development und vorallem auch dies und das</subtitle>
			<link rel="self" href="http://www.frontalaufprall.com/category/php/feed/"/>
			<id>http://www.frontalaufprall.com/category/php/feed/</id>
			<updated>2010-03-15T00:00:23+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">Using Bazaar for PHPUnit Development</title>
		<link href="http://sebastian-bergmann.de/archives/837-Using-Bazaar-for-PHPUnit-Development.html"/>
		<id>http://sebastian-bergmann.de/archives/837-guid.html</id>
		<updated>2009-01-02T08:00:00+00:00</updated>
		<content type="html">&lt;p&gt;Last December, when I was in Australia and started to work on the &lt;a href=&quot;https://launchpad.net/php-object-freezer&quot;&gt;Object_Freezer&lt;/a&gt; code, I &quot;dived into&quot; &lt;a href=&quot;http://bazaar-vcs.org/&quot;&gt;Bazaar&lt;/a&gt; (&lt;code&gt;bzr&lt;/code&gt;) and learned the value of &lt;a href=&quot;http://bazaar-vcs.org/Workflows&quot;&gt;local commits&lt;/a&gt; as they allow me to work offline, e.g. when disconnected during travel.&lt;/p&gt;&lt;p&gt;Thanks to &lt;a href=&quot;http://bazaar-vcs.org/BzrForeignBranches/Subversion&quot;&gt;bzr-svn&lt;/a&gt;, I can now work offline for &lt;a href=&quot;http://www.phpunit.de/&quot;&gt;PHPUnit&lt;/a&gt; development as well.&lt;/p&gt;&lt;p&gt;Here is my setup:&lt;/p&gt;&lt;p&gt;Firstly, setup a local shared repository for storing your branches in and checkout the trunk:&lt;/p&gt;&lt;pre&gt;&lt;b&gt;sb@ubuntu ~ % bzr init-repo --rich-root-pack phpunit&lt;/b&gt;
Shared repository with trees (format: rich-root-pack)
Location:
  shared repository: phpunit&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;sb@ubuntu phpunit % bzr checkout svn+ssh://sb@svn.phpunit.de/var/svn/phpunit/phpunit/trunk&lt;/b&gt;&lt;/pre&gt;&lt;p&gt;I still use &lt;a href=&quot;http://subversion.tigris.org/&quot;&gt;Subversion&lt;/a&gt; natively to deal with the release branches:&lt;/p&gt;&lt;pre&gt;&lt;b&gt;sb@ubuntu phpunit % svn co svn+ssh://sb@svn.phpunit.de/var/svn/phpunit/phpunit/branches/release/3.4&lt;/b&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;sb@ubuntu phpunit % svn co svn+ssh://sb@svn.phpunit.de/var/svn/phpunit/phpunit/branches/release/3.3&lt;/b&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;bzr info&lt;/code&gt; command shows that the local Bazaar branch is related to a remote Subversion branch:&lt;/p&gt;&lt;pre&gt;&lt;b&gt;sb@ubuntu phpunit % bzr info trunk&lt;/b&gt;
Repository checkout (format: rich-root-pack)
Location:
  repository checkout root: trunk
        checkout of branch: svn+ssh://sb@svn.phpunit.de/var/svn/phpunit/phpunit/trunk
         shared repository: .&lt;/pre&gt;&lt;p&gt;Next, create a feature branch and hack away:&lt;/p&gt;&lt;pre&gt;&lt;b&gt;sb@ubuntu phpunit % bzr branch trunk feature&lt;/b&gt;
Branched 205 revision(s).&lt;/pre&gt;&lt;pre&gt;(hack, hack, hack)
&lt;b&gt;sb@ubuntu feature % bzr commit -m &quot;blah blah blah&quot;&lt;/b&gt;
(hack, hack, hack)
&lt;b&gt;sb@ubuntu feature % bzr commit -m &quot;blah blah blah&quot;&lt;/b&gt;&lt;/pre&gt;&lt;pre&gt;&lt;b&gt;sb@ubuntu trunk % bzr update&lt;/b&gt;
&lt;b&gt;sb@ubuntu trunk % bzr merge ../feature&lt;/b&gt;
&lt;b&gt;sb@ubuntu trunk % bzr commit -m &quot;Message for SVN commit.&quot;&lt;/b&gt;&lt;/pre&gt;&lt;p&gt;At least for the foreseeable future, I will not migrate the &lt;a href=&quot;http://www.phpunit.de/wiki/SubversionRepository&quot;&gt;central Subversion repository&lt;/a&gt; of the PHPUnit project to Bazaar as Subversion is a good choice for implementing a &lt;a href=&quot;http://bazaar-vcs.org/Workflows&quot;&gt;centralized workflow&lt;/a&gt; and is well understood by those of my users that use PHPUnit from a Subversion checkout, for instance using &lt;code&gt;svn:externals&lt;/code&gt; to integrate it with their own software configuration management.&lt;/p&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit 3.4.0 - Alpha 1</title>
		<link href="http://sebastian-bergmann.de/archives/836-PHPUnit-3.4.0-Alpha-1.html"/>
		<id>http://sebastian-bergmann.de/archives/836-guid.html</id>
		<updated>2008-12-31T09:10:00+00:00</updated>
		<content type="html">&lt;p&gt;In an effort to end the year on a high note, I have released a first preview release of &lt;a href=&quot;http://www.phpunit.de/wiki/ChangeLog34&quot;&gt;PHPUnit 3.4&lt;/a&gt; today.&lt;/p&gt;&lt;p&gt;The highlights of this new release series include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Support for &lt;a href=&quot;http://www.phpunit.de/ticket/144&quot;&gt;optionally executing each test using a separate PHP process&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Support for &lt;a href=&quot;http://sebastian-bergmann.de/archives/826-Test-Dependencies-in-PHPUnit-3.4.html&quot;&gt;exploiting dependencies between tests to improve defect localization&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Support for mocking SOAP web services based on their WSDL specification&lt;/li&gt;&lt;li&gt;A rewrite of the code generator that is used by the mock object system&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The complete &lt;a href=&quot;http://www.phpunit.de/wiki/ChangeLog34&quot;&gt;ChangeLog&lt;/a&gt; is also available.&lt;/p&gt;&lt;p&gt;PHPUnit 3.4.0alpha1 is not feature-complete and should not be used in production.&lt;/p&gt;&lt;p&gt;Please have a look at the new features and test whether this new version of PHPUnit can run your test suite without problems.&lt;/p&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit 3.3.9</title>
		<link href="http://sebastian-bergmann.de/archives/835-PHPUnit-3.3.9.html"/>
		<id>http://sebastian-bergmann.de/archives/835-guid.html</id>
		<updated>2008-12-29T09:00:20+00:00</updated>
		<content type="html">&lt;ul&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/425&quot; title=&quot;defect: Code Coverage fails if array from Xdebug is not sorted (closed: fixed)&quot;&gt;#425&lt;/a&gt;: Code Coverage fails if array from Xdebug is not sorted. &lt;a href=&quot;http://www.phpunit.de/changeset/4370&quot; title=&quot;- Merge [4368].&quot;&gt;[4370]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/660&quot; title=&quot;defect: PHPUnit_Framework_Assert::getObjectedAttribute fails for inherited private ... (closed: fixed)&quot;&gt;#660&lt;/a&gt;: &lt;tt&gt;PHPUnit_Framework_Assert::getObjectedAttribute()&lt;/tt&gt; fails for inherited private attributes. &lt;a href=&quot;http://www.phpunit.de/changeset/4385&quot; title=&quot;- Merge [4384].&quot;&gt;[4385]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Implemented &lt;a href=&quot;http://www.phpunit.de/ticket/659&quot; title=&quot;enhancement: Implement workaround for PHP bug #46064 (closed: fixed)&quot;&gt;#659&lt;/a&gt;: Implement workaround for PHP bug &lt;a href=&quot;http://bugs.php.net/46064&quot;&gt;&lt;span class=&quot;icon&quot;&gt;#46064&lt;/span&gt;&lt;/a&gt;. &lt;a href=&quot;http://www.phpunit.de/changeset/4360&quot; title=&quot;- Merge [4359].&quot;&gt;[4360]&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit 3.3.8</title>
		<link href="http://sebastian-bergmann.de/archives/833-PHPUnit-3.3.8.html"/>
		<id>http://sebastian-bergmann.de/archives/833-guid.html</id>
		<updated>2008-12-18T07:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/425&quot; title=&quot;defect: Code Coverage fails if array from Xdebug is not sorted (closed: fixed)&quot;&gt;#425&lt;/a&gt;: Code Coverage fails if array from Xdebug is not sorted. &lt;a href=&quot;http://www.phpunit.de/changeset/4270&quot; title=&quot;- Merge [4268].&quot;&gt;[4270]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/649&quot; title=&quot;defect: Fatal error: Unsupported operand types in ... (closed: fixed)&quot;&gt;#649&lt;/a&gt;: &lt;tt&gt;Fatal error: Unsupported operand types in /usr/share/php/PHPUnit/Framework/ComparisonFailure/Scalar.php on line 78&lt;/tt&gt;. &lt;a href=&quot;http://www.phpunit.de/changeset/4287&quot; title=&quot;- Merge [4283].&quot;&gt;[4287]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/650&quot; title=&quot;defect: PHPUnit tries to include non-existent bootstrap file (closed: fixed)&quot;&gt;#650&lt;/a&gt;: PHPUnit tries to include non-existent bootstrap file. &lt;a href=&quot;http://www.phpunit.de/changeset/4303&quot; title=&quot;- Merge [4302].&quot;&gt;[4303]&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

	<entry xml:lang="en">
		<title type="html">PHPUnit 3.3.6</title>
		<link href="http://sebastian-bergmann.de/archives/832-PHPUnit-3.3.6.html"/>
		<id>http://sebastian-bergmann.de/archives/832-guid.html</id>
		<updated>2008-12-13T09:00:00+00:00</updated>
		<content type="html">&lt;ul&gt;&lt;li&gt;Implemented &lt;a href=&quot;http://www.phpunit.de/ticket/636&quot; title=&quot;enhancement: clearstatcache() after setUp() and before test (closed: fixed)&quot;&gt;#636&lt;/a&gt;: &lt;tt&gt;clearstatcache()&lt;/tt&gt; after &lt;tt&gt;setUp()&lt;/tt&gt; and before test. &lt;a href=&quot;http://www.phpunit.de/changeset/4174&quot; title=&quot;- Merge [4172].&quot;&gt;[4174]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/500&quot; title=&quot;defect: Missing 3rd param in call of PEAR_RunTest::run() in PhptTestCase.php (closed: fixed)&quot;&gt;#500&lt;/a&gt;: Bump requirement for PEAR package to version 1.7.1. &lt;a href=&quot;http://www.phpunit.de/changeset/4198&quot; title=&quot;- Merge [4196].&quot;&gt;[4198]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/612&quot; title=&quot;defect: Bootstrap file is not included before including test files (closed: fixed)&quot;&gt;#612&lt;/a&gt;: Bootstrap file is not included before including test files. &lt;a href=&quot;http://www.phpunit.de/changeset/4228&quot; title=&quot;- Merge [4224].&quot;&gt;[4228]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/628&quot; title=&quot;defect: Mocked static functions cause fatal errors (closed: fixed)&quot;&gt;#628&lt;/a&gt;: Mocked static methods cause fatal errors. &lt;a href=&quot;http://www.phpunit.de/changeset/4144&quot; title=&quot;- Merge [4143].&quot;&gt;[4144]&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fixed &lt;a href=&quot;http://www.phpunit.de/ticket/629&quot; title=&quot;defect: @expectedException does not work with the new namespace separator (closed: fixed)&quot;&gt;#629&lt;/a&gt;: &lt;tt&gt;@expectedException&lt;/tt&gt; does not work with the new namespace separator. &lt;a href=&quot;http://www.phpunit.de/changeset/4140&quot; title=&quot;- Merge [4138].&quot;&gt;[4140]&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content>
		<author>
			<name>Sebastian Bergmann</name>
			<email>nospam@example.com</email>
			<uri>http://sebastian-bergmann.de/</uri>
		</author>
		<source>
			<title type="html">Sebastian Bergmann - PHPUnit</title>
			<link rel="self" href="http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss"/>
			<id>http://sebastian-bergmann.de/feeds/categories/14-PHPUnit.rss</id>
			<updated>2010-02-28T11:00:27+00:00</updated>
		</source>
	</entry>

</feed>
