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

<channel>
	<title>Web Mozarts</title>
	<atom:link href="http://webmozarts.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://webmozarts.com</link>
	<description>On The Art Of Web Development</description>
	<lastBuildDate>Mon, 15 Mar 2010 11:48:01 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Why Not To Want 100% Code Coverage</title>
		<link>http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/</link>
		<comments>http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 08:00:20 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Best Practices]]></category>

		<guid isPermaLink="false">http://webmozarts.com/?p=484</guid>
		<description><![CDATA[Although most modern literature agrees that testing is essential for successful software projects, testing has to be done right. Several bad habits can be identified that not only negatively affect testing performance, but also reduce your development speed. One of the first mistakes people make when they first discover testing is trying to reach 100% [...]


Related posts:<ol><li><a href='http://webmozarts.com/2010/03/11/writing-efficient-tests/' rel='bookmark' title='Permanent Link: Writing Efficient Tests'>Writing Efficient Tests</a> <small>Unit testing can be a blessing and curse at the...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Although most modern literature agrees that testing is essential for successful software projects, testing has to be done right. Several bad habits can be identified that not only negatively affect testing performance, but also reduce your development speed. One of the first mistakes people make when they first discover testing is trying to reach 100% code coverage. I was no exception.<span id="more-484"></span></p>
<h3>Test Balance</h3>
<p>The more tests you have for your application, the more difficult it becomes to introduce changes. Everytime you change an existing feature, you have to change <em>at least</em> one test. Everytime you make a refactoring of your project&#8217;s architecture (which you should do frequently), you most likely need to adapt <em>multiple</em> tests. As a rule of thumb you can say that the more tests you have, the more difficult it becomes to make changes in your code.</p>
<p>We know that not to write tests is not a solution. Lots of tests, on the other hand, are bad for maintainability. Instead, try to keep a certain test balance by testing only what is important. The following section shows you one possible approach for identifying important tests called <em>risk-based testing</em>.</p>
<h3>Risk-Based Testing</h3>
<p>The purpose of testing is to avoid regressions in your software resulting of its complexity. These potential regressions can be expressed as risks ranked by their probability and severity. The probability expresses how likely the regression is to occur. The severity expresses how severely the regression would affect the functionality of your application. Both can be expressed in numbers, for instance in a range of 1 to 10 with 10 being the highest severity/probability. Look at the following table for example:</p>
<table border="0">
<tbody>
<tr>
<th>Risk</th>
<th>Probability (<em>P</em>)</th>
<th>Severity (<em>S</em>)</th>
<th>Total (<em>P</em>x<em>S</em>)</th>
</tr>
<tr>
<td><code>getGroup()</code> returns a wrong object</td>
<td>1</td>
<td>3</td>
<td>3</td>
</tr>
<tr>
<td><code>calculatePrice($product)</code> uses a wrong algorithm</td>
<td>7</td>
<td>8</td>
<td>56</td>
</tr>
</tbody>
</table>
<p>The table contains risks for two fictitious methods <code>getGroup()</code> and <code>calculatePrice()</code>. Imagine that the first of these methods only returns an internal property <code>$group</code>. The probability of someone breaking this code by accident is near to non-existent. Assume further that the group is only used for display purposes, so the severity of a broken code is not very high either.</p>
<p>The second method, <code>calculatePrice()</code>, uses an internal algorithm to calculate the price of a product. Because it depends on an external object <code>$product</code>, and because the algorithm is non-trivial, the probability of breaking the code is rather high. Even higher though is the severity of a broken functionality &#8211; what could be worse than wrongly calculated prices.</p>
<p>Is it worth to unit-test <code>getGroup()</code>? Probably not. We calculated an overall total of 3, which (in our scale from 1 to 100) is really not that impressive. Is it, on the other hand, worth to test <code>calculatePrice()</code>? Judge for yourself.</p>
<p>Obviously I selected two extreme examples here. Also you will almost never calculate probabilities and severities for testing single methods like I did it here. But you should try to develop a feeling for what is worth to be tested and what is not.</p>
<h3>Test Complexity</h3>
<p>Now that you have identified which risks you should cover in your test suite, the question is to what extent you should do so. Look at the following to approaches for testing <code>calculatePrice()</code>:</p>
<p><strong>Approach 1: The fair-enough approach</strong></p>
<pre lang="php">$t = new LimeTest();

// @Test: calculatePrice() multiplies the price with the amount

  $product = new Product();
  $product-&gt;price = 100;
  $product-&gt;amount = 2;
  $t-&gt;is($calculator-&gt;calculatePrice($product), 200);</pre>
<p><strong>Approach 2: The safe approach</strong></p>
<pre lang="php">$t = new LimeTest();

// @Before

  $product = new Product();
  $product-&gt;price = 100;

// @Test: calculatePrice() multiplies the price with the amount (amount == 1)

  $product-&gt;amount = 1;
  $t-&gt;is($calculator-&gt;calculatePrice($product), 100);

// @Test: calculatePrice() multiplies the price with the amount (amount == 2)

  $product-&gt;amount = 2;
  $t-&gt;is($calculator-&gt;calculatePrice($product), 200);</pre>
<p>The first approach assumes that testing whether the result equals price multiplied by amount is enough. The test can obviously not check whether the developer has hard-coded a fixed return value of 200 or uses a fixed amount of 2. It expects the developer to be <em>reasonable</em>.</p>
<p>The second approach takes care of these eventualities by writing another test to make sure that changed amounts result in changed outputs. But even now, the developer could write a simple switch statement in <code>calculatePrice()</code> and return either 100 or 200, based on the amount. The test will not notice.</p>
<p>The conclusion is that you can never test your code for <em>all</em> eventualities. However complicated your test may be, there will always be a way to fake the implementation. But is it likely that developers will fake it? Probably not. This being said, the best approach in my opinion is approach 1 because it keeps effort required to adapt or change the test to a minimum.</p>
<h3>Conclusion</h3>
<p>Don&#8217;t try to achieve 100% test coverage. Identify the most important risks, and test for those. Don&#8217;t test for all eventualities either. Always keep in mind that the developers working on your code are somewhat reasonable people. If they aren&#8217;t, you are probably better off without them anyway.</p>


<p>Related posts:<ol><li><a href='http://webmozarts.com/2010/03/11/writing-efficient-tests/' rel='bookmark' title='Permanent Link: Writing Efficient Tests'>Writing Efficient Tests</a> <small>Unit testing can be a blessing and curse at the...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Writing Efficient Tests</title>
		<link>http://webmozarts.com/2010/03/11/writing-efficient-tests/</link>
		<comments>http://webmozarts.com/2010/03/11/writing-efficient-tests/#comments</comments>
		<pubDate>Thu, 11 Mar 2010 17:55:06 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Best Practices]]></category>

		<guid isPermaLink="false">http://webmozarts.com/?p=469</guid>
		<description><![CDATA[Unit testing can be a blessing and curse at the same time. Once you start doing it on a regular basis, it can become an addiction. You test everything, you feel the satisfaction of 110% test coverage giving you confidence in your code. But after a while, testing suddenly seems to slow you down. Everytime [...]


Related posts:<ol><li><a href='http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/' rel='bookmark' title='Permanent Link: Why Not To Want 100% Code Coverage'>Why Not To Want 100% Code Coverage</a> <small>Although most modern literature agrees that testing is essential for...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Unit testing can be a blessing and curse at the same time. Once you start doing it on a regular basis, it can become an addiction. You test everything, you feel the satisfaction of 110% test coverage giving you confidence in your code. But after a while, testing suddenly seems to slow you down. Everytime you make a change in your code you have to adapt several unrelated tests. Adding a <code>&lt;ul&gt;</code>-tag to your template becomes a matter of minutes, rather than seconds. And, worst of all, your test suite is <em>slow</em>.</p>
<p>What happened?<span id="more-469"></span></p>
<h3>Unit vs. System Tests</h3>
<p>To begin with, you need to understand the difference between unit and system tests and the impact both have on testing performance.</p>
<p>Unit tests are <em>atomic</em>. They test classes and components in isolation from any other service they depend on. Such services can be external services, like mailing systems, databases or webservices, and internal services, like a calculator, a data store or similar service classes. Running these tests in isolation gives you several advantages:</p>
<ul>
<li>Speed of execution</li>
<li>Speed of development</li>
<li>Test confidence</li>
</ul>
<p>Speed of execution, because the test doesn&#8217;t need to wait for the related service to process its internal logic. Speed of development, because you (hopefully) don&#8217;t have to adapt the test when you refactor the internals of the related service class or add new features to it. And test confidence, because the test will only fail when the tested class is erroneous, not if any of the related services provide wrong data.</p>
<p>System tests (acceptance or functional tests are a kind of system tests) test whether all the classes in your application collaborate correctly. Because you unit tested these classes in isolation, you had to <em>assume</em> how collaborating services should behave. If this assumption is wrong, no unit test will tell you. And that&#8217;s the space that system tests fill. The big, big disadavantage of system tests is that they are slow. They have to initialize the application, read its configuration files, initialize its database with fresh data (it doesn&#8217;t make a lot of sense to disconnect system tests from the real database) and more. All this takes time.</p>
<p>The conclusion from the last paragraphs is that <em>features</em> of your application should <em>always</em> be tested in unit tests. These tests are fast and guide you to the error if things go wrong. There is nothing more harmful to test performance than testing whether a form works correctly by means of a system test. If the form is a class, write a unit test. If the form is no class, make it one.</p>
<h3 style="font-size: 1,17em;">Decouple Your Code</h3>
<p>If you reach the point that you have lots of unit tests and few system tests, you made the first step towards becoming a test speed king. The second step is to decouple your classes.</p>
<p>Highly coupled code negatively affects your development in several ways. Because your code depends on other classes, these other classes (the dependent-on components or DOCs) all have to be instantiated during testing. Depending on their nature, this process may take time and slow your test down. Introducing new features becomes difficult because it results in lot of test code that needs to be adapted. If one of your classes breaks, not only the test of the class fails, but also several other tests of dependent classes. Shortly spoken: Extending and maintaining the application becomes a nightmare.</p>
<p>To decouple your code, get a clear picture of the responsibilities inside of your application. If a class does too much, tear it apart like a wild monkey smelling a banana in a big pile of waste paper.</p>
<p class="note">The following code samples are based on the PHP5 frameworks <a href="http://www.symfony-project.com" title="The symfony framework" target="_blank" class="liexternal">symfony</a>, <a href="http://www-doctrine-project.org" title="Doctrine Object-Relational Mapping for PHP5" target="_blank" class="liexternal">Doctrine</a> and <a href="http://github.com/bschussek/lime" title="Lime 2. A usable testing framework for PHP5." target="_blank" class="liexternal">Lime 2</a>. The same concepts can be applied to other frameworks and languages just as well.</p>
<p>Let&#8217;s look at a (slightly modified) example I recently saw in a code review:</p>
<pre lang="php">class sfValidatorUsername
{
  public function clean($value)
  {
    $user = Doctrine_Query::create()
      -&gt;from('User u')
      -&gt;where('u.name = ? AND u.active = 1', $value)
      -&gt;fetchOne();

    if (is_null($user))
    {
      throw new sfValidatorError('invalid', $this);
    }

    return $value;
  }
}</pre>
<p>It should be pretty obvious what this code is doing. What is the problem? The validator depends on the database. This is not a problem per se, but querying the database for <code>User</code> objects is beyond the validator&#8217;s responsibilities. This task should rather be done by your data acccess objects (DAOs), entity stores, tables or whatever you call them. And these objects can easily be injected into the validator using <em>Dependency Injection</em>.</p>
<p>Happy that we have identified this code smell, we can already start removing it:</p>
<pre lang="php">class sfValidatorUsername
{
  protected $table;

  public function __construct(UserTable $table)
  {
    $this-&gt;table = $table;
  }

  public function clean($value)
  {
    if (is_null($this-&gt;table-&gt;findActive($value))
    {
      throw new sfValidatorError('invalid', $this);
    }

    return $value;
  }
}</pre>
<p>We removed the database code and instead inject the table object into the constructor. The responsibility for fetching an active user by its name was outsourced to the table.</p>
<p class="info">An even faster solution is to only count the matching user objects in the database instead of querying and hydrating them. But that&#8217;s not in the scope of this article.</p>
<p>So, mummy, is our test faster already? Is it?</p>
<h3>Replace Dependencies During Testing</h3>
<p>No, kid. We are still using the <code>UserTable</code> when testing the validator &#8211; of course, because we need it. So what can we do?</p>
<p>Now that the validator only depends on the <code>UserTable</code>, and not on some mystical database query magic, we can replace the <code>UserTable</code> &#8211; which is tested somewhere else and assumed to be working &#8211; with a fake implementation. This is usually called <em>stubbing</em> (because you are replacing it with a non-functional <em>stub</em>). With Lime 2, you can do it like this:</p>
<pre lang="php">$t = new LimeTest();

// @Test: clean() returns the cleaned value if the user is found

  $table = $t-&gt;stub('UserTable');
  $table-&gt;findActive('bob')-&gt;returns(new User());
  $table-&gt;replay();
  $validator = new sfValidatorUsername($table);

  $t-&gt;is($validator-&gt;clean('bob'), 'bob');</pre>
<p>The stub acts <em>as if</em> it was the real <code>UserTable</code> object, but in reality it has no internal logic at all. So compared to the real table, the stub is very fast.</p>
<p class="info">More documentation about Lime 2 and its stubbing/mocking capabilities can currently be found on the <a href="http://github.com/bschussek/lime/tree/master/doc/" target="_blank" class="liexternal">Lime 2 GitHub repository</a>.</p>
<p>A word of caution shall be spoken. You should only replace <em>services</em> (classes that process some data and return a result) with stubs, not <em>entities</em> (classes that simply contain data). Otherwise changing your domain model (the entities) will soon become a nightmare.</p>
<h3>Testing With Databases</h3>
<p>Hurray! The validator test is so fast, I can execute it 10 times in a row and it&#8217;s still fun. One more time! Nice.</p>
<p>But wait &#8211; we can&#8217;t decouple everything from the database, can we? Of course, we can&#8217;t. Code that is responsible for collaborating with the database, like the above <code>UserTable</code>, needs to access the database. In order for that test to work, the database has to be bootstrapped and filled with data. Because tests should run in isolation from each other, the database further needs to be reset <em>before every single test</em>.</p>
<p>Now a common mistake that severely affects testing performance can often be seen in <em>symfony</em> projects. Many developers use a test database on their development DBMS, like a MySQL server. This database is filled with the content of <em>fixtures.yml</em>, which usually contains all fixture data commonly used to test the application in the browser. And for good reasons this is very slow:</p>
<ul>
<li>Most DBMS store data on the file system. Hard disk access is an expensive operation.</li>
<li>Filling the database with all the test data takes a lot of time</li>
<li>Parsing YAML files is slow</li>
</ul>
<p>So ideally we don&#8217;t use the database and don&#8217;t use any test data. Obviously, that&#8217;s not possible.</p>
<h3>In-Memory Databases</h3>
<p>What <em>is</em> possible is to use an in-memory database. While CPU access on the hard disk usually takes around 4 170 000 ns (nano seconds) for 7200 RPM drives, memory access only takes around 14 ns! Thus, using an in-memory database is a very cheap way to increase your testing performance immensely. Unfortunately not all database vendors offer in-memory alternatives for their file-based DBMS (such as MySQL). In such cases I use SQLite in-memory databases, because SQLite supports most of the SQL92 standard, which is generally sufficient for testing purposes.</p>
<p>If you use <em>symfony</em> with <em>Doctrine</em>, you can place the following code snippet into your <em>bootstrap/unit.php</em> file which initializes the SQLite in-memory database:</p>
<pre lang="php">// initialize Doctrine
$cacheFile = sprintf('sf_autoload_unit_doctrine_%s.data', md5(__FILE__));
$autoload = sfSimpleAutoload::getInstance(sys_get_temp_dir().'/'.$cacheFile);
$autoload-&gt;addDirectory(ROOT_DIR.'/lib/model');
$autoload-&gt;addDirectory(ROOT_DIR.'/lib/form');
$autoload-&gt;addDirectory(ROOT_DIR.'/lib/filter');
$autoload-&gt;register();

$database = new sfDoctrineDatabase(array(
  'name' =&gt; 'doctrine',
  'dsn' =&gt; 'sqlite::memory:'
));

// load all missing model files
Doctrine::loadModels(ROOT_DIR.'/lib/model');

/**
 * Reloads the database.
 */
function reload()
{
  // close the connection to the in-memory database to recreate the database
  Doctrine_Manager::getInstance()-&gt;getCurrentConnection()-&gt;close();

  // create the database tables from the loaded models
  Doctrine::createTablesFromModels();

  // clear the Doctrine cache
  foreach (Doctrine::getLoadedModels() as $model)
  {
    Doctrine::getTable($model)-&gt;clear();
  }
}</pre>
<p class="info">Make sure the constant <code>ROOT_DIR</code> is defined and points to the root of the tested project (your real project or the fixture project).</p>
<p class="note">You might wonder why the <code>$cacheFile</code> is required. This parameter allows us to run multiple tests in parallel while still leveraging autoloading performance by using a cache.</p>
<p>The real interesting piece of code is the <code>reload()</code> function. It allows you to recreate the database on demand. Whenever you write a test that requires a fresh database, call <code>reload()</code> and you are good to go.</p>
<h3>Fixture Management</h3>
<p>As described above, it is important to keep an eye on the test data that is loaded into your database. The more data you load, the more time it takes. Loading the whole <em>fixtures.yml</em> is a recipe for slow (not only because it contains a lot of data, but also because the YAML file must be parsed).</p>
<p>A much more efficient solution is to programmatively create and load test data on-the-fly. Only create what you need, and nothing more. Below you can find a sample test for our above method <code>UserTable::findActive()</code>:</p>
<pre lang="php">$t = new LimeTest();

// @Test: findActive() returns an active user by username

  reload();
  $user = new User();
  $user-&gt;username = 'bob';
  $user-&gt;active = true;
  $user-&gt;save();
  $table = Doctrine::getTable('User');
  $t-&gt;is($table-&gt;findActive('bob'), $user);</pre>
<p>This test is really fast now. The database is created in-memory, exactly one single <code>User</code> object is inserted and that&#8217;s it. The downside is that creating all the fixture data inline becomes a little messy, especially if you have to fill a lot of properties only because they are defined as <code>NOT NULL</code> in the database.</p>
<h3>Creation Methods</h3>
<p>To work around this issue, I prefer the <em>Creation Method</em> pattern by Gerard Meszaros[1]:</p>
<blockquote><p>We should use a <em>Creation Method</em> whenever consructing a <em>Fresh Fixture</em> requires significant complexity and we value <em>Tests as Documentation</em>.</p></blockquote>
<p>The pattern is very simple. Encapsulate the code required to create an object within a utility function that can be reused across your project. My rule of thumb is to write creation methods for all tested Doctrine records and initialize all <code>NOT NULL</code> fields and relations with default values so that the object can be saved without further modification. Because this leads to a lot of code duplication, I also use a base function <code>createObject()</code>.</p>
<pre lang="php">function createUser(array $properties = array())
{
  return createObject('User', $properties, array(
    // NOT NULL properties
    'username' =&gt; 'francis',
    ...
    // NOT NULL relations
    'Group' =&gt; createGroup(),
    ...
  );
}

function createObject($class, array $properties, array $defaultProperties)
{
  $properties = array_merge($defaultProperties, $properties);

  $object = new $class();
  foreach ($properties as $property =&gt; $value)
  {
    $object-&gt;set($property, $value);
  }

  return $object;
}</pre>
<p>Now you can call <code>createUser()</code> everytime you need to create and save a new <code>User</code> object. Optionally, you can inject property values into the constructor.</p>
<pre lang="php">$t = new LimeTest();

// @Test: findActive() returns an active user by username

  reload();
  $user = createUser(array(
    'username' =&gt; 'bob',
    'active' =&gt; true,
  ));
  $user-&gt;save();
  $table = Doctrine::getTable('User');
  $t-&gt;is($table-&gt;findActive('bob'), $user);</pre>
<div class="info">
<h4>A Few More Utility Methods</h4>
<p>In the following snippet you can find some more utility methods that I find very useful when dealing with fresh fixtures. Put them into your <em>bootstrap/unit.php</em> file or where ever they suit you best.</p>
<pre lang="php">/**
 * Saves all objects passed as arguments.
 * @param Doctrine_Record $object1
 * @param Doctrine_Record ...
 */
function save()
{
  foreach (func_get_args() as $object)
  {
    $object-&gt;save();
  }
}

/**
 * Creates a collection containing the passed objects.
 * @param Doctrine_Record $object1
 * @param Doctrine_Record ...
 */
function collection()
{
  if (func_num_args() == 0)
  {
    throw new LogicException('You must pass at least one object');
  }

  $objects = func_get_args();
  $collection = new Doctrine_Collection(get_class($objects[0]));
  foreach ($objects as $object)
  {
    $collection-&gt;add($object);
  }

  return $collection;
}</pre>
<p>The functions can be used like this:</p>
<pre lang="php">$user1 = createUser();
$user2 = createUser();
$user3 = createUser();
save($user1, $user2, $user3);

$coll = collection($user1, $user3);
// etc.</pre>
</div>
<h3>Pulling All Levers</h3>
<p>Now that we have optimized our test code to the highest degree, there is one last thing we can do: Increase the hardware power of the test computers and optimize the test suite to utilize its power.</p>
<p>Because most CPUs nowadays feature multiple cores, you should design your test suite for parallel processing. Make sure that no two tests are using the same resources (another benefit of the in-memory databases) and use a testing framework of your choice that supports multiprocessing.</p>
<p>Lime 2, for example, supports multiprocessing by adding the <code>--processes</code> option:</p>
<pre class="code">$ php lime --processes=16</pre>
<p>While most of my CPU cores are pretty bored when running the test suite in one process, using multiple processes sparks a sudden increase in activity. Not only that, I could record speed increases of over 300% (15 minutes in one process, 4.5 minutes in 16 processes).</p>
<h3>Conclusion</h3>
<p>As I have tried to portray in this article, writing tests alone is not enough to improve your development. If tests are slow or prevent change, your developers won&#8217;t run and use them. Fortunately there are several ways to make changes easier and to increase test speed.</p>
<p>To summarize:</p>
<ol>
<li>Test single features in unit tests. System tests should only be used to verify whether the classes collaborate correctly within different processes.</li>
<li>Decouple your classes. This allows introduction of changes without having to adapt multiple tests.</li>
<li>Only classes that really need to should deal with remote services. Replace these classes with stubs in all other tests.</li>
<li>Choose the fastest version of a remote service available. When you test database classes, use in-memory databases.</li>
<li>Only create databases during testing when you really need them</li>
<li>Only load data into the database that you really need. Do so programmatively without taking the overhead of parsing XML or YAML files.</li>
<li>Make use of multiprocessing, if supported by your testing framework.</li>
</ol>
<p>How is your testing experience? Are you satisfied with the performance of your tests?</p>
<h3>References</h3>
<p>[1] Gerard Meszaros: <em>xUnit Test Patterns. Refactoring Test Code</em>. Addison-Wesley, 2007. Page 415</p>


<p>Related posts:<ol><li><a href='http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/' rel='bookmark' title='Permanent Link: Why Not To Want 100% Code Coverage'>Why Not To Want 100% Code Coverage</a> <small>Although most modern literature agrees that testing is essential for...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://webmozarts.com/2010/03/11/writing-efficient-tests/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Thank You</title>
		<link>http://webmozarts.com/2009/09/06/thank-you/</link>
		<comments>http://webmozarts.com/2009/09/06/thank-you/#comments</comments>
		<pubDate>Sun, 06 Sep 2009 07:32:57 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Community]]></category>

		<guid isPermaLink="false">http://webmozarts.com/?p=449</guid>
		<description><![CDATA[Yesterday I returned back to Vienna from Symfony Day Cologne 2009. The conference was amazingly well organized and many people deserve credits for making it such a great experience.
Thank you Andreas and Dennis for putting uncounted hours into planning the event, guiding us around the city, spending the night before fixing the wireless connection and [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Yesterday I returned back to Vienna from <a href="http://www.symfonyday.com" title="Symfony Day Cologne 2009. Official Website." target="_blank" class="liexternal">Symfony Day Cologne 2009</a>. The conference was amazingly well organized and many people deserve credits for making it such a great experience.</p>
<div id="attachment_461" class="wp-caption aligncenter" style="width: 692px"><img class="size-full wp-image-461" title="Symfony Day Cologne 2009" src="http://webmozarts.com/wp-content/uploads/2009/09/3885868975_c9a286802c_b.jpg" alt="Symfony Day Cologne 2009" width="682" height="455" /><p class="wp-caption-text">© Nicolas Perriault</p></div>
<p>Thank you Andreas and Dennis for putting uncounted hours into planning the event, guiding us around the city, spending the night before fixing the wireless connection and for taking care of all the other small things that usually go by unnoticed. Thank you Isabelle for your Cologne crash course and for organizing our flights and the perfect accommodation. Thank you Nicolas for your many thoughtful advices, I really appreciate them. Thank you Xavier, Stefan, Jon and Sebastian for your refreshing company; I really enjoyed the lengthy walks around the city, even though my foot complained somewhat. Thank you all the attendees who gave me feedback about my work and my presentation. Thank you Interlution for letting us take part in your 10 year anniversary party. And thank you all the other people involved in making this event a success.</p>
<p>Events like this one are really important for the community. They put faces behind names, make friends, open up new opportunities and spread ideas. They are what open source truly is about.</p>
<p>As another result of the conference, this blog features a new page <a href="http://webmozarts.com/talks/" class="liinternal">Talks</a> where I included the slides of my presentation <strong>Best Practice Testing with Lime 2.</strong> And to those who annoyed me about Twitter &#8211; apparently some new account <a href="http://twitter.com/webmozart" title="@webmozart at Twitter" target="_blank" class="liexternal">@webmozart</a> has been created over there. Don&#8217;t know who it is, but don&#8217;t expect him to tweet too much.</p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://webmozarts.com/2009/09/06/thank-you/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony Day Cologne 2009</title>
		<link>http://webmozarts.com/2009/09/03/symfony-day-cologne-2009/</link>
		<comments>http://webmozarts.com/2009/09/03/symfony-day-cologne-2009/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 09:21:34 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Community]]></category>

		<guid isPermaLink="false">http://webmozarts.com/?p=413</guid>
		<description><![CDATA[Today, I will take the plane to Cologne to attend the first german Symfony Day. The one-day conference is going to take place on friday on the 28th floor of the Köln Triangle, the second highest building in Cologne. Located directly at the bank of the Rhine, the tower offers a magnificient view over the [...]


Related posts:<ol><li><a href='http://webmozarts.com/2009/09/06/thank-you/' rel='bookmark' title='Permanent Link: Thank You'>Thank You</a> <small>Yesterday I returned back to Vienna from Symfony Day Cologne...</small></li>
<li><a href='http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/' rel='bookmark' title='Permanent Link: Why Not To Want 100% Code Coverage'>Why Not To Want 100% Code Coverage</a> <small>Although most modern literature agrees that testing is essential for...</small></li>
<li><a href='http://webmozarts.com/2010/03/11/writing-efficient-tests/' rel='bookmark' title='Permanent Link: Writing Efficient Tests'>Writing Efficient Tests</a> <small>Unit testing can be a blessing and curse at the...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Today, I will take the plane to Cologne to attend the first german <a href="http://www.symfonyday.com/de/" title="Symfony Day Cologne 2009. Official Website." target="_blank" class="liexternal">Symfony Day</a>. The one-day conference is going to take place on friday on the 28th floor of the <a href="http://www.koelntriangle.de/index_eng.html" title="Köln Triangle. High-rise office block at the bank of the Rhine." target="_blank" class="liexternal">Köln Triangle</a>, the second highest building in Cologne. Located directly at the bank of the Rhine, the tower offers a magnificient view over the city. <a href="http://www.interlutions.de/" title="Interlutions. The company organizing the Symfony Day Cologne 2009." target="_blank" class="liexternal">Interlutions</a>, the company organizing the event seems to have done a very good job.</p>
<p style="text-align: center;">
<div id="attachment_429" class="wp-caption aligncenter" style="width: 683px"><img class="size-full wp-image-429" title="View from the Köln Triangle" src="http://webmozarts.com/wp-content/uploads/2009/09/triangle02.jpg" alt="View from the Köln Triangle" width="673" height="450" /><p class="wp-caption-text">Image Courtesy of KoelnTriangle.de</p></div>
<p>The conference will offer a full-day workshop held by Stefan Koopmanschap for those who are just getting started with symfony. Advanced symfony users can attend five promising speeches by <a href="http://prendreuncafe.com" title="Personal Blog of Nicolas Perriault" target="_blank" class="liexternal">Nicolas Perriault</a>, <a href="http://lacot.org" title="Personal Blog of Xavier Lacot." target="_blank" class="liexternal">Xavier Lacot</a>, Rob Bors and <a href="http://www.jwage.com" title="Website of Jonathan Wage." target="_blank" class="liexternal">Jonathan Wage</a>, who is accountable for two presentations. I had the pleasure to be invited as the fifth speaker, and I am going to talk about unit testing.</p>
<p>Automated software testing, when applied in a real context, is not always as easy as it may sometimes be portrayed. You need experience to design your software in a testable fashion, discipline to keep writing tests when pressure keeps increasing, tools to support your testing needs in the best way possible and knowledge to employ these tools efficiently. If any of these aspects is lacking, your team may very quickly end up not writing any tests at all. Even if you fight your way through the battle and manage to keep test coverage high, chances are that your tests become very slow. A bad test performance, in turn, prevents people from running them frequently enough &#8211; and turns all your testing efforts into a waste of time.</p>
<p>In my presentation I want to give you a deeper insight on what testing is all about. Not only do I want to present you best practices that worked for me, I also want you to <em>understand</em> the testing process so that you can go on developing best practices for yourself. I will try to focus on pratical examples; nevertheless I expect you to have a fair knowledge of writing and reading unit and functional tests with lime. For all those who won&#8217;t be able to join, the slides will be uploaded on this blog as soon as I probably can.</p>
<p>The presentation will also give you the opportunity to get a first glance of what <a href="http://trac.symfony-project.org/browser/tools/lime/branches/2.0" title="Lime 2. The successor of symfony's testing framework lime." target="_blank" class="liexternal">Lime 2</a> is going to offer you. I have been busy developing the successor of lime over the last months and am happy to see that it is steadily approaching alpha release. The detailed release plan is soon to be published on the <a href="http://www.symfony-project.org/blog/" title="Official blog of the symfony project." target="_blank" class="liexternal">symfony blog</a>.</p>
<p>I am already excitedly looking forward to meeting you all!</p>


<p>Related posts:<ol><li><a href='http://webmozarts.com/2009/09/06/thank-you/' rel='bookmark' title='Permanent Link: Thank You'>Thank You</a> <small>Yesterday I returned back to Vienna from Symfony Day Cologne...</small></li>
<li><a href='http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/' rel='bookmark' title='Permanent Link: Why Not To Want 100% Code Coverage'>Why Not To Want 100% Code Coverage</a> <small>Although most modern literature agrees that testing is essential for...</small></li>
<li><a href='http://webmozarts.com/2010/03/11/writing-efficient-tests/' rel='bookmark' title='Permanent Link: Writing Efficient Tests'>Writing Efficient Tests</a> <small>Unit testing can be a blessing and curse at the...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://webmozarts.com/2009/09/03/symfony-day-cologne-2009/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Why sfContext::getInstance() Is Bad</title>
		<link>http://webmozarts.com/2009/07/01/why-sfcontextgetinstance-is-bad/</link>
		<comments>http://webmozarts.com/2009/07/01/why-sfcontextgetinstance-is-bad/#comments</comments>
		<pubDate>Wed, 01 Jul 2009 07:24:31 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Best Practices]]></category>

		<guid isPermaLink="false">http://webmozarts.com/?p=380</guid>
		<description><![CDATA[The &#8220;default&#8221; context does not exist.
Is there any symfony developer out there who never stumbled upon this dreadful error message? I doubt it. Recently, a lot of posts have been made on the user mailing list asking for explanations and fixes. A quick search on Google for the exact phrase even returns 480 results!
The reason [...]


Related posts:<ol><li><a href='http://webmozarts.com/2010/03/11/writing-efficient-tests/' rel='bookmark' title='Permanent Link: Writing Efficient Tests'>Writing Efficient Tests</a> <small>Unit testing can be a blessing and curse at the...</small></li>
<li><a href='http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/' rel='bookmark' title='Permanent Link: Why Not To Want 100% Code Coverage'>Why Not To Want 100% Code Coverage</a> <small>Although most modern literature agrees that testing is essential for...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<blockquote><p>The &#8220;default&#8221; context does not exist.</p></blockquote>
<p>Is there any symfony developer out there who never stumbled upon this dreadful error message? I doubt it. Recently, a lot of posts have been made on the <a href="http://groups.google.com/group/symfony-users" title="Symfony users Google Group" target="_blank" class="liexternal">user mailing list</a> asking for explanations and fixes. A quick search on Google for the exact phrase even returns 480 results!</p>
<p>The reason for this error is quite simple though: It&#8217;s because you used <code>sfContext::getInstance()</code>. And you should never do that.<span id="more-380"></span></p>
<h3>MVC and the Context</h3>
<p>The class <code>sfContext</code> is the glue of the <em>controller layer</em> in symfony. It keeps all the relevant controller classes together: <code>sfUser</code>, <code>sfResponse</code>, <code>sfRequest</code>, <code>sfController</code> as well as some others. The reason for its existence is simplicity. These classes now only need a reference to the context to access each other. The class <code>sfController</code>, for instance, contains a protected member variable <code>$context</code>, by which it can access all the other objects without having to store seperate references.</p>
<p><code>sfContext</code> implements the <a href="http://en.wikipedia.org/wiki/Singleton_pattern" title="The Singleton pattern at Wikipedia" target="_blank" rel="nofollow" class="liwikipedia">Singleton</a> design pattern. Thus you can retrieve one of the few context instances by calling <code>sfContext::getInstance()</code> with an optional first parameter: The name of the context. If the first parameter is not given, the name is assumed to be &#8220;default&#8221;. But <code>sfContext</code> is no real Singleton. No new instance will ever be created when you call <code>sfContext::getInstance()</code>. Instead, you need to call <code>sfContext::createInstance()</code> first. If you miss to do that, you will receive exactly the error at the introduction of my post.</p>
<h3>Why to Avoid Singletons</h3>
<p>The Singleton pattern is actually one of the worst design patterns by the Gang-of-Four[1]. Because you hard-code the name of the singleton class, you create a dependency that is hard and partially impossible to substitute from outside. As a result, your class becomes unflexible and very hard to unit-test. Let&#8217;s look at a common mistake:</p>
<pre lang="php">class Product
{
  public function save()
  {
    if (sfContext::getInstance()-&gt;getUser()-&gt;hasAttribute('foobar'))
    {
      // do something
    }
  }
}</pre>
<p><em>Listing 1</em></p>
<p>This implementation bears the following problems:</p>
<h4>Problem #1: Flexibility</h4>
<p>If you have multiple <code>sfUser</code> instances, you are not able to tell the product on which instance it should depend. The product always fetches the instance registered in the context. Also, if the context is not available (for instance in console tasks), the <code>save()</code> method fails.</p>
<h4>Problem #2: Testability</h4>
<p>For testing the <code>Product</code> class, you have to create the context including all of its dependencies. That means parsing <code>factories.yml</code>, reading the configuration files, instantiating <code>sfController</code>, <code>sfRequest</code> and many more classes. Doing so adds substantial overhead to your tests and makes them slow and prone to errors. If any of the operations during the context instantiation fails, your <code>Product</code> test will suddenly fail, even if the class <code>Product</code> is perfectly fine!</p>
<h3>How to Avoid Singletons</h3>
<p>Instead of hard-coding the call to <code>sfContext::getInstance()</code>, you should pass the context object directly to the object that needs it. If you don&#8217;t even need the context, but only one of its references like the user, pass that object instead.</p>
<pre lang="php">class Product
{
  protected $user = null;

  protected function setUser(sfUser $user)
  {
    $this-&gt;user = $user;
  }

  public function save()
  {
    if ($this-&gt;user instanceof sfUser &amp;&amp; $this-&gt;user-&gt;hasAttribute('foobar'))
    {
      // do something
    }
  }
}</pre>
<p><em>Listing 2</em></p>
<p>This technique is called <em>Dependency Injection</em>. If you are not familiar with Dependency Injection, I recommend you to read Fabien Potencier&#8217;s <a href="http://fabien.potencier.org/article/11/what-is-dependency-injection" title="What Is Dependency Injection by Fabien Potencier" target="_blank" class="liexternal">introduction to Dependency Injection</a>. Basically there are two ways two inject dependencies into an object:</p>
<h4>Constructor Injection</h4>
<p>This type of Dependency Injection is used when a dependency is <em>required</em>. Because the dependency needs to be passed in the constructor, no object can ever be created when this dependency is not fulfilled.</p>
<pre lang="php">class Product
{
  protected $user = null;

  protected function __construct(sfUser $user)
  {
    $this-&gt;user = $user;
  }
}</pre>
<p><em>Listing 3</em></p>
<h4>Setter Injection</h4>
<p>This type of Dependency Injection is used when a dependency is <em>optional</em>. Because you can never be sure whether the setter has been called, you always have to verify whether the object exists before accessing its operations and properties, as we did in Listing 2.</p>
<p>Alternatively, you can also use setter injection for required dependencies if you can not override the constructor without breaking the class (this is the case for Doctrine records). In that case, you simply throw an exception if the dependency is not available.</p>
<pre lang="php">class Product
{
  public function save()
  {
    if (!$this-&gt;user instanceof sfUser)
    {
      throw new LogicException('The user must be set before saving');
    }
  }
}</pre>
<p><em>Listing 4</em></p>
<h3>What You Gained</h3>
<p>Because you can now inject any user object into your class, you can test the <code>Product</code> class very easily:</p>
<pre lang="php">class StubUser extends sfUser
{
  public function hasAttribute($name)
  {
    return $name == 'foobar';
  }
}

$t-&gt;comment('Products with the attribute "foobar" do something special upon saving');

  $p = new Product();
  $p-&gt;setUser(new StubUser());
  $p-&gt;save();
  $t-&gt;is(...);</pre>
<p><em>Listing 5</em></p>
<h3>Exceptions</h3>
<p>In very few cases, you cannot avoid accessing the context by using <code>sfContext::getInstance()</code>. This is almost always the case when symfony manages the construction of an object. If you configure symfony to use a custom object by modifying <code>factories.yml</code>, you still won&#8217;t be able to inject custom objects.</p>
<p class="info">This will change as soon as symfony uses the new <a href="http://components.symfony-project.org/dependency-injection/" title="Website of the Symfony Dependency Injection Component" target="_blank" class="liexternal">Dependency Injection container</a> for the construction of the core classes.</p>
<p>An example for this problem is extending <code>sfResponse</code>. You can tell symfony to use a custom response, but you cannot tell symfony to inject the context or other objects into it (except for if you write a custom <code>sfFactoryConfigHandler</code>). In this case, and because <code>sfResponse</code> is part of the <em>controller layer</em>, you should be pragmatic and just use <code>sfContext::getInstance()</code>.</p>
<h3>Conclusion</h3>
<p>Always try to avoid calling <code>sfContext::getInstance()</code>. Many of symfony&#8217;s classes in the <em>controller layer</em> already store a reference to the context, so you can use that one instead. If no reference is available, inject the reference to the context or to whichever class you need.</p>
<h3>References</h3>
<p>[1] E. Gamma, R. Helm, R. Johnson, J. Vlissides: <em>Design Patterns. Elements of Reusable Object-Oriented Software</em>. Addison-Wesley, 1995</p>


<p>Related posts:<ol><li><a href='http://webmozarts.com/2010/03/11/writing-efficient-tests/' rel='bookmark' title='Permanent Link: Writing Efficient Tests'>Writing Efficient Tests</a> <small>Unit testing can be a blessing and curse at the...</small></li>
<li><a href='http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/' rel='bookmark' title='Permanent Link: Why Not To Want 100% Code Coverage'>Why Not To Want 100% Code Coverage</a> <small>Although most modern literature agrees that testing is essential for...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://webmozarts.com/2009/07/01/why-sfcontextgetinstance-is-bad/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Easy Unit Testing</title>
		<link>http://webmozarts.com/2009/06/30/easy-unit-testing/</link>
		<comments>http://webmozarts.com/2009/06/30/easy-unit-testing/#comments</comments>
		<pubDate>Tue, 30 Jun 2009 09:06:41 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://webmozarts.com/?p=334</guid>
		<description><![CDATA[Unit testing is a very important task of professional, scalable software development. Many tools exist to support unit testing in one or another way. All tools come with advantages and drawbacks. One of the best known test frameworks in the PHP world is PHPUnit. With the release of symfony, Fabien Potencier released another new testing [...]


Related posts:<ol><li><a href='http://webmozarts.com/2010/03/11/writing-efficient-tests/' rel='bookmark' title='Permanent Link: Writing Efficient Tests'>Writing Efficient Tests</a> <small>Unit testing can be a blessing and curse at the...</small></li>
<li><a href='http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/' rel='bookmark' title='Permanent Link: Why Not To Want 100% Code Coverage'>Why Not To Want 100% Code Coverage</a> <small>Although most modern literature agrees that testing is essential for...</small></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Unit testing is a very important task of professional, scalable software development. Many tools exist to support unit testing in one or another way. All tools come with advantages and drawbacks. One of the best known test frameworks in the PHP world is <a href="http://www.phpunit.de" title="Website of the test framework PHPUnit" target="_blank" class="liexternal">PHPUnit</a>. With the release of <a href="http://www.symfony-project.org" title="Official website of the web PHP framework &quot;symfony&quot;" target="_blank" class="liexternal">symfony</a>, <a href="http://fabien.potencier.org" title="Fabien Potencier's blog" target="_blank" class="liexternal">Fabien Potencier</a> released another new testing framework for PHP: <a href="http://trac.symfony-project.org/browser/tools/lime/trunk/lib/lime.php" title="Source code of the test framework &quot;lime&quot;" target="_blank" class="liexternal">lime</a>. The biggest advantage of <em>lime</em> over <em>PHPUnit</em> surely is the conciseness of the written test code. There are several disadvantages as well, which include bad test encapsulation due to the lack of support for fixture setup and teardown, and missing support for mock object generation.</p>
<p>Today I will briefly speak about the advantages of both frameworks, and how they can be combined to result in a slicker, powerful testing framework. I will show you how easy testing really can be! And you will be able to try it out, because all the required code has already been released in  <a href="http://www.symfony-project.org/plugins/sfLimeExtraPlugin" title="The symfony plugin sfLimeExtraPlugin" target="_blank" class="liexternal">sfLimeExtraPlugin</a>.</p>
<p><span id="more-334"></span></p>
<h3>Introduction</h3>
<p>In the following sections, I will refer to a set of example classes that I will briefly describe here for your better understanding:</p>
<pre lang="php">class User
{
  protected $storage;

  public function User(SessionStorageInterface $storage)
  {
    $this-&gt;storage = $storage;
  }

  public function setAttribute($name, $value)
  {
    $this-&gt;storage-&gt;write($name, $value);
  }

  public function getAttribute($name)
  {
    return $this-&gt;storage-&gt;read($name);
  }
}</pre>
<p>The <strong>user</strong> class offers methods to store data of a user in a <strong>session storage</strong> that you need to pass to its constructor.</p>
<pre lang="php">interface SessionStorageInterface
{
  public function write($key, $value);
  public function read($key);
}</pre>
<p>Let&#8217;s assume that <code>SessionStorageInterface</code> specifies how session storages have to look like. They need methods to write values into the underlying layer, be it the file system or database, and methods to read values.</p>
<p>We will be writing unit tests for the <code>User</code> class. We don&#8217;t want to use a real session storage class though, because we don&#8217;t want the test to rely on the file system or a database. Thus we will create a <em>fake implementation</em> of <code>SessionStorageInterface</code>:</p>
<pre lang="php">class StubSessionStorage implements SessionStorageInterface
{
  private $name;
  private $value;

  public function write($name, $value)
  {
    $this-&gt;name = $name;
    $this-&gt;value = $value;
  }

  public function read($name)
  {
    return $name == $this-&gt;name ? $this-&gt;value : null;
  }
}</pre>
<p class="note">Fake implementations like this are called &#8220;Stubs&#8221;. Obviously, they would never make sense in a production environment. Their sole purpose is to help us testing, as in our case, the <code>User</code> class.</p>
<h3>PHPUnit and the xUnit Family</h3>
<p>Back in 1999, <a href="http://www.threeriversinstitute.org/Kent%20Beck.htm" title="Kent Beck's page at the Three Rivers Institute" target="_blank" class="liexternal">Kent Beck</a> wrote &#8220;the mother of all unit          testing frameworks&#8221;; it was called &#8220;SUnit&#8221; and supported unit testing for <a href="http://en.wikipedia.org/wiki/Smalltalk" title="Smalltalk at Wikipedia" target="_blank" rel="nofollow" class="liwikipedia">Smalltalk</a>[1]. <a href="http://sunit.sourceforge.net" title="Unit testing framework for Smalltalk" target="_blank" class="liexternal">SUnit</a> lead to a further testing framework, that Beck wrote in cooperation with Erich Gamma: <a href="http://www.junit.org" title="Unit testing framework for Java" target="_blank" class="liexternal">jUnit</a>, for Java. Today, <em>jUnit</em> is the most popular and widely-used unit testing framework for Java and hence it was ported to many other languages: <em>CppUnit</em> for C++, <em>NUnit</em> for C# or <em>PHPUnit</em> for PHP. All those frameworks together are often referred to as the<strong> xUnit family</strong>[2].</p>
<p><a href="http://www.phpunit.de/" title="Website of the test framework PHPUnit" target="_blank" class="liexternal">PHPUnit</a> is a high-quality port of <em>jUnit</em> to PHP written by <a href="http://sebastian-bergmann.de" title="Sebastian Bergmann's personal website" target="_blank" class="liexternal">Sebastian Bergmann</a>, currently available in stable version 3.3. A typical test case with <em>PHPUnit</em> looks like this:</p>
<pre lang="php">class UserTest extends PHPUnit_Framework_TestCase
{
  private $sessionStorage;
  private $user;

  public function setUp()
  {
    $this-&gt;sessionStorage = new StubSessionStorage();
    $this-&gt;user = new User($this-&gt;sessionStorage);
  }

  public function testAttributesAreReadFromTheSession()
  {
    // fixture setup
    $this-&gt;sessionStorage-&gt;write('Foo', 'Bar');
    // execute test
    $value = $this-&gt;user-&gt;getAttribute('Foo');
    // verify results
    $this-&gt;assertEquals($value, 'Bar', 'The value was read from the session');
  }

  public function testAttributesAreWrittenToTheSession()
  {
  // ...
  }
}</pre>
<p>What does this code do? First of all, we see that the test code is organized within a <em>test class</em>. This means that you can use all the power of object-orientation for testing, but it also implies that a certain amount of code overhead is required for defining the class&#8217;s structure.</p>
<p>All methods prefixed with &#8220;test&#8221; are <em>test methods</em>. These methods test that a certain requirement is successfully fulfilled by the tested class. Because most of the test methods need a common set of objects (the &#8220;fixture&#8221;), these objects are created in the method <code>setUp()</code>, which is executed once before every test method. As a result, each test method works with fresh objects; influences of the previously executed test methods are largely prevented.</p>
<p>We also notice that test methods have descriptive names (which, to be honest, tend to look very weird). The purpose is to allow the reader to quickly scan the method names of a test class to receive an impression of the tested class&#8217;s abilities.</p>
<p>In our single, exemplary test method, we first set up the fixture; we tell the fake session storage, which has been instantiated in <code>setUp()</code>, to return the value &#8220;Bar&#8221; when the method <code>read("Foo")</code> is called. Then we call <code>getAttribute("Foo")</code> on the user, which we expect to read from the session. In the last line of code, we assert that the returned value has indeed been read from the session.</p>
<h3>Lime</h3>
<p><em>Lime</em> is a testing framework created by <a href="http://fabien.potencier.org/" title="Fabien Potencier's blog" target="_blank" class="liexternal">Fabien Potencier</a> for testing the source code of the web framework <a href="http://www.symfony-project.org/" title="Official website of the web PHP framework &quot;symfony&quot;" target="_blank" class="liexternal">symfony</a>. It is based on the <em>Test::More</em> Perl library and aims for a very concise and readable test code. The above test in <em>lime</em> looks like this:</p>
<pre lang="php">$t = new lime_test(1);

$t-&gt;comment('Attributes are read from the session');

  // fixture
  $s = new StubSessionStorage();
  $u = new User($s);
  $s-&gt;write('Foo', 'Bar');
  // test
  $value = $u-&gt;getAttribute('Foo');
  // assertions
  $t-&gt;is($value, 'Bar', 'The value was read from the session');

$t-&gt;comment('Attributes are written to the session');

  // ...</pre>
<p>Contrary to <em>PHPUnit</em>, <em>lime</em> tests are written in a procedural way. Thus the code is more concise, because you don&#8217;t need to write down structural information of the code.</p>
<p>Initially a <code>lime_test</code> object is created, which tracks the number of expected, successful and failing tests and offers several methods to make testing easier. Each test case is, by convention, introduced by a comment that explains the tests purpose. Therefore the method <code>comment()</code> is called, which does also print the comment on the console when executing the test.</p>
<p>The test fixture has to be created manually for each test case. This is very prone to errors, because you can easily forget to reassign a variable once in a while. Then you&#8217;ll suddenly deal with an object left over from a previous test, which may lead to strange and unexpected test results.</p>
<h3>Pro and Contra</h3>
<p>Let us roughly sum up the advantages and disadvantages of both frameworks:</p>
<p><strong>PHPUnit&#8230;</strong></p>
<ul>
<li>&#8230; is verbose</li>
<li>&#8230; offers magic methods like <code>setUp()</code>, which initiates your test fixture before every test</li>
<li>&#8230; offers other convenient tools not covered in this blog post, like mocking support</li>
</ul>
<p><strong>lime&#8230;</strong></p>
<ul>
<li>&#8230; is concise and readable</li>
<li>&#8230; requires code repetition</li>
<li>&#8230; requires you to initiate your fixture manually</li>
</ul>
<p>sfLimeExtraPlugin extends <em>lime</em> and tries to introduce concepts of the xUnit family without making tests more verbose. Quite the opposite, because sfLimeExtraPlugin supports <em>annotations</em>, the written tests are even more concise than without this plugin.</p>
<h3>Annotation-Driven Tests</h3>
<p>The above test case, written with support of sfLimeExtraPlugin, looks like this:</p>
<pre lang="php">$t = new lime_test_simple(1);

// @Before
$s = new StubSessionStorage();
$u = new User($s);

// @Test: Attributes are read from the session
// fixture
$s-&gt;write('Foo', 'Bar');
// test
$value = $u-&gt;getAttribute('Foo');
// assertions
$t-&gt;is($value, 'Bar', 'The value was read from the session');

// @Test: Attributes are written to the session
// ...</pre>
<p class="info">This test leads to <em>exactly the same</em> test results and console output as the test written with plain <em>lime</em> earlier in this post.</p>
<p>sfLimeExtraPlugin introduces the new class <code>lime_test_simple</code>. When you use that test class, you can mark sections of your code with so-called <a href="http://en.wikipedia.org/wiki/Java_annotation" title="Java annotations at Wikipedia" target="_blank" rel="nofollow" class="liwikipedia">annotations</a>. The test class knows, for example, that code annotated with <code>@Before</code> must be executed before every test case.</p>
<p>Single test cases are annotated with <code>@Test</code>. You can also add a comment about the purpose of the test. Note that the comment now really is a <em>PHP comment</em>, which is usually highlighted in a different color by code editors and thus disturbs the eye much less than the call to the method <code>comment()</code>.</p>
<p>Several other annotations are available. I&#8217;ll shortly list all of them:</p>
<dl>
<dt>@Test</dt>
<dd>A test case</dd>
<dt>@Before</dt>
<dd>Executed before each test case</dd>
<dt>@After</dt>
<dd>Executed after each test case</dd>
<dt>@BeforeAll</dt>
<dd>Executed once before all test cases</dd>
<dt>@AfterAll</dt>
<dd>Executed once after all test cases</dd>
</dl>
<p>With these annotations, you can easily structure your test code and avoid code duplication while making your tests easier to read.</p>
<h3>Testing for Exceptions</h3>
<p>Contrary to plain <code>lime_test</code>, <code>lime_test_simple</code> allows you to automatically test whether exceptions are thrown. With plain <code>lime_test</code>, such a test would look like this:</p>
<pre lang="php">$t-&gt;comment('setAttribute() throws an exception if the data contains &lt;script&gt; tags');

  // fixture
  $u = new User(new StubSessionStorage());
  // test
  try
  {
    $u-&gt;setAttribute('&lt;script&gt;alert("Evil!")&lt;/script&gt;');
    $t-&gt;fail('setAttribute() throws an "InvalidArgumentException"');
  }
  catch (InvalidArgumentException $e)
  {
    $t-&gt;pass('setAttribute() throws an "InvalidArgumentException"');
  }</pre>
<p>In this test, we try to catch the expected exception. If the exception is caught, we mark  the test as passed, otherwise as failed.</p>
<p>With <code>lime_test_simple</code>, this is much easier:</p>
<pre lang="php">// @Before
$u = new User(new StubSessionStorage());

// @Test: setAttribute() throws an exception if the data contains &lt;script&gt; tags
// fixture
$t-&gt;expect('InvalidArgumentException');
// test
$u-&gt;setAttribute('&lt;script&gt;alert("Evil!")&lt;/script&gt;');</pre>
<h3>Mock and Stub Objects</h3>
<p>Like <em>PHPUnit</em>, sfLimeExtraPlugin allows you to automatically generate fake objects, which are referred to as &#8220;Mocks&#8221; and &#8220;Stubs&#8221;. So far, we had to write our fake <code>StubSessionStorage</code> class by hand. With sfLimeExtraPlugin this is not needed anymore. The component <code>lime_mock</code> will generate such a class automatically:</p>
<pre lang="php">// @Before
$s = lime_mock::create('SessionStorageInterface');
$u = new User($s);

// @Test: Attributes are read from the session
// fixture
$s-&gt;read('Foo')-&gt;returns('Bar');
$s-&gt;replay();
// test
$value = $u-&gt;getAttribute('Foo');
// assertions
$t-&gt;is($value, 'Bar', 'The value was read from the session');</pre>
<p>Before the execution of each test case, we tell <code>lime_mock</code> to generate a new fake instance of <code>SessionStorageInterface</code>. In the test itself, we teach the fake object which methods can be called with what parameters and which value should be returned. We can also specify other constraints, such as how often a method may be called or which exception it should throw.</p>
<p>Then we switch the fake object into &#8220;replay&#8221; mode. In this mode, the fake object will behave just the way that we configured it before.</p>
<p class="note">You can create stubs for interfaces, classes or abstract classes. You can even create stubs for non-existing classes, which is very convenient if you develop test-driven.</p>
<p>Because this topic deserves a whole blog post of its own, I won&#8217;t go into more detail here. For more information about Mocks and Stubs in general and their usage in sfLimeExtraPlugin in specific can be found on the <a href="http://www.symfony-project.org/plugins/sfLimeExtraPlugin/0_2_0?tab=plugin_readme" title="Readme page of sfLimeExtraPlugin" target="_blank" class="liexternal">readme page</a> of sfLimeExtraPlugin.</p>
<h3>Final Words</h3>
<p>I personally think that tests can be written in a much more concise and readable way with sfLimeExtraPlugin. Because it also introduces other powerful features of the xUnit-family, the plugin aims to be an essential tool of every symfony developer who wants to seriously unit test his or her application.</p>
<p>Currently the plugin is available in version 0.2.0alpha. That means that the API may change before the final release (though this is unlikely) and that the code is not being considered 100% stable. I recommend you to try it out nevertheless and give me feedback about its usefulness or shortcomings, report bugs etc.</p>
<p>What do you think about sfLimeExtraPlugin? Do you think you may ever use it?</p>
<h3>References</h3>
<p>[1] Kent Beck, Donald G. Firesmith: <em>Kent Beck&#8217;s Guide to Better Smalltalk</em>. Cambridge University Press, 1998. Page 408</p>
<p>[2] Gerard Meszaros: <em>xUnit Test Patterns. Refactoring Test Code</em>. Addison-Wesley, 2007. Page 75</p>


<p>Related posts:<ol><li><a href='http://webmozarts.com/2010/03/11/writing-efficient-tests/' rel='bookmark' title='Permanent Link: Writing Efficient Tests'>Writing Efficient Tests</a> <small>Unit testing can be a blessing and curse at the...</small></li>
<li><a href='http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/' rel='bookmark' title='Permanent Link: Why Not To Want 100% Code Coverage'>Why Not To Want 100% Code Coverage</a> <small>Although most modern literature agrees that testing is essential for...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://webmozarts.com/2009/06/30/easy-unit-testing/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Speedup: Profile your symfony app using Xdebug</title>
		<link>http://webmozarts.com/2009/05/01/speedup-performance-profiling-for-your-symfony-app/</link>
		<comments>http://webmozarts.com/2009/05/01/speedup-performance-profiling-for-your-symfony-app/#comments</comments>
		<pubDate>Fri, 01 May 2009 10:17:09 +0000</pubDate>
		<dc:creator>Klemens</dc:creator>
				<category><![CDATA[Tips & Tricks]]></category>

		<guid isPermaLink="false">http://webmozarts.com/?p=276</guid>
		<description><![CDATA[Hi! A warm welcome to Web Mozarts also from my side. It took some time to write my first post, but here it is!
Your app is slow? If the symfony web debug toolbar doesn&#8217;t give you the details you want, you can take a real deep look into your application using the profiling options of [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Hi! A warm welcome to Web Mozarts also from my side. It took some time to write my first post, but here it is!</p>
<p>Your app is slow? If the symfony <a href="http://www.symfony-project.org/book/1_2/16-Application-Management-Tools#chapter_16_sub_web_debug_toolbar" title="symfony web debug toolbar" target="_blank" class="liexternal">web debug</a> toolbar doesn&#8217;t give you the details you want, you can take a real deep look into your application using the profiling options of <a href="http://www.xdebug.org/" title="Xdebug homepage" target="_blank" class="liexternal">Xdebug</a>.</p>
<p>In this tutorial we will set up Xdebug to profile your application and then we&#8217;ll analyse the output with <a href="http://kcachegrind.sourceforge.net/html/Home.html" target="_blank" class="liexternal">KCachegrind</a>.</p>
<p class="note">By the way: Xdebug has a lot of other useful features. One that comes automatically is the nicely formated php debugging output in case of errors including the full call stack. KCachegrind on the other hand has very interesting graphical output features like the call graph. In the case of symfony the call graph can be like an interesting expedition into the functionality of the framework.</p>
<p><span id="more-276"></span></p>
<h3>Installation</h3>
<p>We&#8217;ll do the installation using Ubuntu Linux, but it works similar for other unixes or even Windows with a WAMP stack. Ah yes &#8211; we assume you have the correct environment for symfony installed (Apache, PHP5, &#8230;).</p>
<p class="note">KCachegrind is not available for Windows. You can use <a href="http://sourceforge.net/projects/wincachegrind/" target="_blank" class="liexternal">WinCacheGrind</a> instead although it doesn&#8217;t provide the graphical goodies.</p>
<p>Download and install:</p>
<pre lang="php">sudo aptitude install php5-xdebug kcachegrind</pre>
<p>Ubuntu automatically inserts the Xdebug module in the php ini files:</p>
<pre lang="php"># /etc/php5/conf.d/xdebug.ini
zend_extension=/usr/lib/php5/20060613+lfs/xdebug.so</pre>
<p>Now let&#8217;s restart apache to load the new configuration:</p>
<pre lang="php">sudo apache2ctl restart</pre>
<p>Let&#8217;s provoke an error and let us see if Xdebug works. I put an invalid function call into a php script:</p>
<pre lang="php">// apps/frontend/modules/myModule/actions.class.php
class myModuleActions extends sfActions
{
  public function executeIndex()
  {
    invalid_function();
  }
}</pre>
<p>Now we get the typical Xdebug output including the call stack in the browser, so we know it works:<br />
<a href="http://webmozarts.com/wp-content/uploads/2009/04/xdebug_trace.png" ><img class="alignnone size-medium wp-image-296" src="http://webmozarts.com/wp-content/uploads/2009/04/xdebug_trace-300x215.png" alt="xdebug_trace" width="300" height="215" /></a></p>
<h3>Enable profiling</h3>
<p>The profiling capability of Xdebug has to be explictly enabled because it produces A LOT of output and slows down the application serverely.</p>
<p>If you use .htaccess for your symfony project this is the easiest way to enable the profiling:</p>
<pre lang="php"># web/.htaccess

# append at the end of the file:
php_value xdebug.profiler_enable 1
php_value xdebug.profiler_output_dir /tmp</pre>
<p>If you don&#8217;t use .htaccess, or if you want to profile a cli php script, you have to enable the profiling in your php.ini (cli stands for command line interface). Example for the cli:</p>
<pre lang="php"># /etc/php5/cli/conf.d/xdebug.ini

# append at the end of the file:
xdebug.profiler_output_dir = "/tmp"
xdebug.profiler_enable = 1</pre>
<p>Don&#8217;t forget to restart apache if you changed the php.ini config!</p>
<h3>Data galore&#8230;</h3>
<p>Ok, let&#8217;s profile something! Just fire up your webbrowser and load any page of your local symfony project.<br />
Xdebug now creates a &#8220;cachegrind&#8221; file like &#8220;cachegrind.out.22076 in your /tmp/ directory.</p>
<p>Here&#8217;s how a cachgrind file looks like:</p>
<pre lang="php">version: 0.9.6
cmd: /var/www/ullright/web/index.php
part: 1

events: Time

fl=php:internal
fn=php::realpath
38 98

fl=/var/www/ullright/plugins/ullCorePlugin/lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php
fn=sfCoreAutoload-&gt;__construct
50 93
cfn=php::dirname
calls=1 0 0
38 2
cfn=php::realpath
calls=1 0 0
38 98</pre>
<p>It basically records which function was called from which script file, how many times it was called and how long the execution took.</p>
<p>Now that isn&#8217;t really human readable, is it?</p>
<p>So let&#8217;s open the cachegrind file with KCachegrind. It looks something like this:</p>
<p><a href="http://webmozarts.com/wp-content/uploads/2009/05/kcachegrind-overview.png" ><img class="alignnone size-medium wp-image-309" src="http://webmozarts.com/wp-content/uploads/2009/05/kcachegrind-overview-300x187.png" alt="kcachegrind-overview" width="300" height="187" /></a></p>
<p>So what have we got here? On the left side you see the &#8220;Flat Profile&#8221;. A list of all function and method calls. From left to right:</p>
<ul>
<li>Incl. &#8211; The cost of the function including all child functions</li>
<li>Self &#8211; The cost of the function itself</li>
<li>Called &#8211; How many times a function was called</li>
<li>Function &#8211; Which function</li>
<li>Location &#8211; Script file</li>
</ul>
<p>A good starting point is to click on &#8220;Called&#8221; to see which functions are called the most often. It&#8217;s also interesting to order by &#8220;Self&#8221; to see which method itself took the most time.</p>
<p>On the right side I selected the tab &#8220;Call Graph&#8221; which shows the sequence of the function calls starting with &#8220;{main}&#8221;. For symfony it&#8217;s usually &#8220;web/index.php&#8221;.</p>
<p>The number of nodes in the call graph is limited by the relative percentage of the execution time. Per default only functions that take more than 5% of the execution time are displayed. Get a more detailed graph by right clicking into the call graph and selecting &#8220;Graph -&gt; Min. node cost -&gt; 1%&#8221;. You can also doube click on any node to see a more detailed child-graph.</p>
<p><a href="http://webmozarts.com/wp-content/uploads/2009/05/kcachegrind-doctrine.png" ><img class="alignnone size-medium wp-image-314" src="http://webmozarts.com/wp-content/uploads/2009/05/kcachegrind-doctrine-300x187.png" alt="kcachegrind-doctrine" width="300" height="187" /></a></p>
<p>Here is a nice detailed graph showing the internals of a doctrine query.  I&#8217;d like to invite you to explore your symfony app using the call graph &#8211; it surely is an interesting journey and you can learn a lot about the architecture of symfony.</p>
<p>Coming to an end I&#8217;d like to hear about your experiences and findings about performance profiling:</p>
<ul>
<li>What tools do you use?</li>
<li>What are your best practices?</li>
</ul>
<p>Looking forward to interesting discussions &#8211; have a nice day!</p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://webmozarts.com/2009/05/01/speedup-performance-profiling-for-your-symfony-app/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Improving the Forms: Layouts and Formatters</title>
		<link>http://webmozarts.com/2009/04/23/improving-the-forms-layouts-and-formatters/</link>
		<comments>http://webmozarts.com/2009/04/23/improving-the-forms-layouts-and-formatters/#comments</comments>
		<pubDate>Thu, 23 Apr 2009 12:01:40 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Thinking Ahead]]></category>

		<guid isPermaLink="false">http://webmozarts.com/?p=230</guid>
		<description><![CDATA[Keeping all parts of a website consistent is one of the most time consuming tasks of a web designer. Spending this time is worth doing, because the more consistent the look and feel of your website is, the more professional it appears to its users.
I will show you today how symfony could help you keeping [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Keeping all parts of a website consistent is one of the most time consuming tasks of a web designer. Spending this time is worth doing, because the more consistent the look and feel of your website is, the more professional it appears to its users.</p>
<p>I will show you today how symfony could help you keeping all of your forms consistent with very little work left for you to do.<span id="more-230"></span></p>
<div class="note">
<p>The concept presented in this article series is not implemented in symfony. It has been developed together with a few other people in the community. With these articles, I would like to receive feedback about how you like the concept and how it can be improved.</p>
<ol>
<li><a href="http://webmozarts.com/2009/04/12/improving-the-forms/" title="Improving the Symfony Forms Framework" class="liinternal">Improving the Forms</a></li>
<li><a href="http://webmozarts.com/2009/04/19/improving-the-forms-field-groups/" title="Adding Field Groups to the Symfony Forms Framework" class="liinternal">Improving the Forms: Field Groups</a></li>
<li>Improving the Forms: Layouts and Formatters</li>
</ol>
</div>
<h3>A Quick Look Back</h3>
<p>In my last post I <a href="http://webmozarts.com/2009/04/19/improving-the-forms-field-groups/" title="Improving the Forms: Field Groups" class="liinternal">introduced you to the concept of field groups</a>. Field groups are similar to embedded forms in that they group a set of form fields together and enable combined data binding and validation. They differ from embedded forms in that they can combine multiple fields to enter one single value. I showed you the example of a password field with two fields, that is used to enter one single value: The password.</p>
<p>Here is the code for the user profile form that we have developed in the course of this article series:</p>
<pre lang="php">// lib/form/doctrine/ProfileForm.class.php
class ProfileForm extends sfFormDoctrine
{
  protected $user = null;

  public function __construct(sfUser $user)
  {
    $this-&gt;user = $user;
  }

  public function configure()
  {
    $this-&gt;addField('name', new sfTextField(15))
         -&gt;setHelp('Your full name, f.i. "John Travolta"');
    $this-&gt;addField('email', new sfEmailField())
         -&gt;setHelp('A valid email address, f.i. "john.travolta@gmail.com"');
    $this-&gt;addField('password', new VerifiedPasswordField())
         -&gt;setHelp('Must not be "pulpfiction"');

    $this-&gt;setFinalValidator(
      new sfValidatorCallback($this, 'comparePasswordAndName')
    );

    if (!$this-&gt;user-&gt;hasCredential('admin'))
    {
      $this-&gt;getField('name')-&gt;setEditable(false);
    }
  }

  public function comparePasswordAndName(sfValidator $validator, array $values)
  {
    if ($values['name'] == $values['password'])
    {
      throw new sfValidatorError('The password must not be the same as the name',
          'password');
    }
  }
}</pre>
<p>I invite you to compare this form with the <a href="http://webmozarts.com/2009/04/12/improving-the-forms/" title="Improving the Forms" class="liinternal">original symfony implementation of the same functionality</a> shown in my first post.</p>
<h3>Form Layouts</h3>
<p>Today I want to present you another advantage of the field groups. You can use &#8220;layouts&#8221; on them to automate the generation of HTML code in a very flexible way.</p>
<p>Right now, symfony offers two alternatives to create the HTML code of your forms.</p>
<ol>
<li>Use one of the built-in form formatters &#8220;list&#8221; and &#8220;table&#8221;. These formatters are very unflexible because the whole form will be rendered in the same way. You cannot modify the formatters to render some parts as fieldsets, others as multi-column fields etc.</li>
<li>Code the HTML by hand in your templates. This way gives the most power to web designers. Unfortunately it also leads to a lot of code duplication in your templates that cannot be easily resolved by using partials. Maintaining this duplicate code is <a href="http://fabien.potencier.org" title="Fabien Potenciers favourite quote" target="_blank" class="liexternal">quite repetitive, tedious, and error prone</a>™ <img src='http://webmozarts.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </li>
</ol>
<p>Layouts help you to solve this problem. But what exactly are layouts?</p>
<p>In general, a layout is a set of different classes (the &#8220;formatters&#8221;) that specify how different parts of a form should be rendered. Look at the following sketch to get an idea of what layouts can do for you:</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-234" title="Layout examples" src="http://webmozarts.com/wp-content/uploads/2009/04/layouts.gif" alt="Layout examples" width="606" height="139" /></p>
<p>Usually, layouts render the individual fields in rows with the label to the left and the field to the right. You can change individual fields or field groups to be rendered in a different way: As fieldset (useful for field groups), with the label to the right (useful for checkboxes), with no label at all or with your very own custom formatter.</p>
<p>But layouts can do much more than formatting the individual rows: They also know how the formatted fields should be visually organized. You can, for example, display all fields in a horizontal row or organize them in a grid with multiple columns.</p>
<p>Each field group (the form is also a field group) has exactly one layout assigned that is used to organize the fields in this group. Because field groups can be nested within each other, you can also nest different layouts. Let&#8217;s look at a basic example that can be achieved very easily:</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-235" title="Profile form with layouts" src="http://webmozarts.com/wp-content/uploads/2009/04/profile-form-layouts.png" alt="Profile form with layouts" width="525" height="324" /></p>
<p>The password field and the permissions field group are configured to be formatted as fieldset. The permissions field group itself has a multi-column layout applied. Later in this post I will show you how little PHP code is necessary to achieve this result.</p>
<p>Apart from the visual aspect, layouts specify which HTML code will be used to render the form. <code>sfListLayout</code> renders the form in an <code>ul</code> tag, <code>sfTableLayout</code> renders the form in a &#8230; guess what .. right, in a <code>table</code> tag. Of course you can also implement your own layout that renders the whole form in a combination of <code>address</code> and <code>blockquote</code> tags, if that makes sense to you (tag misuse at its best!).</p>
<h3>Multi-Column Layouts</h3>
<p>Layouts with multiple columns are especially interesting. They help you to display a lot of information in little, well-organized space.</p>
<p>If you use <code>ul</code>-tags to render your form, a multi-column layout can be achieved very easily. You just need to change the CSS of the <code>li</code>-tags to make them floating. By giving them a fixed width, you can control how many form fields are displayed in a row.</p>
<p>There is a big problem with this solution though: Fields are first rendered from left to right, then from top to bottom.</p>
<p>This can be a problem if your fields are sorted in a specific order. A good example are large lists of checkboxes. If the labels of these fields are sorted alphabetically, users expect them to be sorted from top to bottom, then from left to right.</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-237" title="Layouts with multiple columns" src="http://webmozarts.com/wp-content/uploads/2009/04/multi-column-layouts.gif" alt="Layouts with multiple columns" width="401" height="138" /></p>
<p>Layouts are able to deal with this problem easily. You can configure the number of columns and the order of the fields (&#8220;horizontal&#8221; or &#8220;vertical&#8221;) simply by passing these options to the layout&#8217;s constructor.</p>
<h3>Show Me the Code</h3>
<p>Configuring layouts in your form is easy. Every class inheriting from <code>sfFormFieldGroup</code> (thus also <code>sfForm</code>) offers the method <code>setLayout()</code>. To this method you can pass an instance of the layout you want to use.</p>
<pre lang="php">  public function configure()
  {
    $this-&gt;setLayout(new sfListLayout());
  }</pre>
<p>The different layout classes allow different options that you can pass to their constructor. Two such options are the number of columns and the order in which the fields are put into these columns.</p>
<pre lang="php">  public function configure()
  {
    $this-&gt;setLayout(new sfListLayout(array(
      'columns' =&gt; 3,
      'order'   =&gt; sfLayout::VERTICAL,
    )));
  }</pre>
<p>With as little code as this you have configured your form to organize all fields in 3 columns in a vertical order using <code>ul</code> and <code>li</code>-tags. You can achieve the same result using an HTML table by passing an instance of <code>sfTableLayout</code> instead of <code>sfListLayout</code>.</p>
<p>The format of the individual form fields can be modified by calling the method <code>setFormat()</code> on the field. To this method you pass the name of the format you want to use. The names of the different formats are declared in the layout class, as you will see later.</p>
<pre lang="php">  public function configure()
  {
    $this-&gt;addField('password', new VerifiedPasswordField())
         -&gt;setFormat('fieldset');
  }</pre>
<p>After this simple definition, the password fields are rendered as in the picture above. Depending on the layout, there can be many more formats like &#8220;leftlabel&#8221; (the default), &#8220;nolabel&#8221; or &#8220;rightlabel&#8221;. Look at the first sketch in this post to see what these look like.</p>
<h3>A More Complex Example</h3>
<p>Now that we have learned about the basics, we can look at how to configure our user profile form to be displayed like in the above picture.</p>
<p>First, we tell our form to be rendered as HTML list.</p>
<pre lang="php">  public function configure()
  {
    $this-&gt;setLayout(new sfListLayout());</pre>
<p>Now we add the fields as we did before. Note the format that we have set on the password field to render it as a fieldset.</p>
<pre lang="php">    $this-&gt;addField('name', new sfTextField(15))
         -&gt;setHelp('Your full name, f.i. "John Travolta"');
    $this-&gt;addField('email', new sfEmailField())
         -&gt;setHelp('A valid email address, f.i. "john.travolta@gmail.com"');
    $this-&gt;addField('password', new VerifiedPasswordField())
         -&gt;setHelp('Must not be "pulpfiction"')
         -&gt;setFormat('fieldset');</pre>
<p>Just for fun, we&#8217;ll add a few checkboxes to our form to demonstrate how a multigrid layout is integrated.</p>
<pre lang="php">    $permissions = array(
      'admin', 'blog-editor', 'content-editor',
      'publisher', 'file-editor', 'comment-editor',
    );
    $this-&gt;addField('permissions', new sfCheckboxList($permissions))
         -&gt;setHelp('Choose one or more permissions for this user')
         -&gt;setFormat('fieldset')
         -&gt;setLayout(new sfListLayout(array('columns' =&gt; 3));</pre>
<p>The last thing left is to declare the final validator and the user credential check again, but this code has not changed.</p>
<p>Let&#8217;s sum up what we have learned:</p>
<ol>
<li>A <strong>format</strong> is the definition of how a <em>single field</em> is rendered</li>
<li>A <strong>layout</strong> is the definition of how a <em>group of fields</em> is organized</li>
</ol>
<h3>But What About the Web Designers?</h3>
<p>I can hear voices screaming that I am violating the MVC separation with this proposal. But honestly, I am not. <img src='http://webmozarts.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  We still have one specific component that is responsible for generating the output of our form: The <code>sfLayout</code> instance. You can simply modify the way your form is rendered by exchanging its layout, which is what MVC is all about.</p>
<p class="info">Many people misunderstand the MVC concept as it is applied in symfony. Although the view layer consists mostly of templates, it is not restricted to that. MVC simply requires you to program separate decoupled layers that can be easily exchanged. Whether you put the code of these layers in templates, classes or coke cans does not matter.</p>
<p>The good news is that you can do all the configuration from within your templates, if you don&#8217;t like to do it in your <code>configure()</code> method. All of the above methods are accessible using <code>sfForm</code>&#8217;s array access syntax. Together with a set of easy convenience methods, even web designers could configure the form&#8217;s format.</p>
<pre lang="php">&lt;?php $form-&gt;setLayout('list') ?&gt;
&lt;?php $form['password']-&gt;setFormat('fieldset') ?&gt;
&lt;?php $form['permissions']-&gt;setFormat('fieldset') ?&gt;
&lt;?php $form['permissions']-&gt;setLayout('list', array('columns' =&gt; 2)) ?&gt;

&lt;?php echo $form ?&gt;</pre>
<p class="note">For small projects with one or only very few forms, I recommend you to not use layouts and formatters, if that eases the life of your web designers. You can still output the form the oldfashioned way and write all the HTML by hand.</p>
<h3>sfLayout Internals</h3>
<p>In the last part of our travel to the magic layout wonderland, I want to explain some of the internals of <code>sfLayout</code> to you.</p>
<p class="note">
The information in this section is only relevant when you create your own layout. You hardly ever need this information to simply configure your form.
</p>
<p>All layouts must implement <code>sfLayoutInterface</code>.</p>
<pre lang="php">interface sfLayoutInterface
{
  public function createFieldFormatter($format = null);
  public function createFieldGroupFormatter();
}</pre>
<p>Layouts follow the <em>Abstract Factory Pattern</em>. That means that any class implementing <code>sfLayoutInterface</code> simply creates instances of other classes that are connected in some way.</p>
<p>Let&#8217;s visualize this very technical definition with a simple example: <code>sfListLayout</code> is able to create new <code>sfFieldFormatter</code> instances as well as <code>sfFieldGroupFormatter</code> instances. Because both instances must know that the form is rendered as <code>ul</code>-list, they structurally belong together. If you use a different layout, you get a different set of formatters that again know about each other. That&#8217;s what this pattern is about.</p>
<p class="info">It is the responsibility of <code>sfFieldFormatter</code> and <code>sfFieldGroupFormatter</code> instances to turn the fields/field groups into HTML code.</p>
<p><code>sfLayoutInterface::createFieldFormatter()</code> has one single parameter &#8220;format&#8221;. This format is exactly the format string that you have set on the form fields earlier using <code>setFormat()</code>. For each given format, the layout knows which object to return.</p>
<pre lang="php">$layout = new sfListLayout();
$formatter = $layout-&gt;createFieldFormatter('rightlabel');
echo get_class($formatter);

// returns "sfRightLabelListFieldFormatter"</pre>
<p>The great thing is that you never need to know about these long class names, because the layout you use hides them from you. All returned objects share the same interface: <code>sfFieldFormatterInterface</code>. You only ever need to know about this interface and never about the concrete class you receive.</p>
<pre lang="php">interface sfFieldFormatterInterface
{
  public function render($id, $label, $value, $help, array $attributes = array());
}</pre>
<h3>Conclusion</h3>
<p>Enough theory for today. I hope I was able to give you an idea of what power layouts can give to you. As you have seen, they can reduce code duplication in large applications with many forms and simplify the presentation of forms. There is much more to tell about layouts, but this post has grown long enough.</p>
<p>How do you like the layouts? Is this idea worth the time following?</p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://webmozarts.com/2009/04/23/improving-the-forms-layouts-and-formatters/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Improving the Forms: Field Groups</title>
		<link>http://webmozarts.com/2009/04/19/improving-the-forms-field-groups/</link>
		<comments>http://webmozarts.com/2009/04/19/improving-the-forms-field-groups/#comments</comments>
		<pubDate>Sun, 19 Apr 2009 10:56:41 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Thinking Ahead]]></category>

		<guid isPermaLink="false">http://webmozarts.com/?p=195</guid>
		<description><![CDATA[Today I want to follow up on my last post about improving the forms in symfony. David Hermann wrote a quite interesting reply on his blog. I want to take some of his ideas and enhance them even further. The goal is to be able to reuse as much code as possible when creating applications [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Today I want to follow up on my <a href="http://webmozarts.com/2009/04/12/improving-the-forms/" title="Improving the Forms" class="liinternal">last post about improving the forms</a> in symfony. David Hermann wrote <a href="http://blog.vworld.at/2009/04/14/improving-the-forms-even-more/" title="Improving the forms even more. David's virtual world. A blog about symfony and software in general." target="_blank" class="liexternal">a quite interesting reply on his blog</a>. I want to take some of his ideas and enhance them even further. The goal is to be able to reuse as much code as possible when creating applications with lots of different forms.</p>
<p>This post will be different though. While I only made assumptions in my last post without any code verifying that my ideas are implementable, I do have a prototype implementation now.<span id="more-195"></span></p>
<div class="note">
<p>The concept presented in this article series is not implemented in symfony. It has been developed together with a few other people in the community. With these articles, I would like to receive feedback about how you like the concept and how it can be improved.</p>
<ol>
<li><a href="http://webmozarts.com/2009/04/12/improving-the-forms/" title="Improving the Symfony Forms Framework" class="liinternal">Improving the Forms</a></li>
<li>Improving the Forms: Field Groups</li>
<li><a href="http://webmozarts.com/2009/04/23/improving-the-forms-layouts-and-formatters/" title="Using Layouts to Easily Generate the HTML Code of Symfony Forms" class="liinternal">Improving the Forms: Layouts and Formatters</a></li>
</ol>
</div>
<h3>Where Did We Stop?</h3>
<p>In my last post, we left with the following form:</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-202" title="Basic Profile Form" src="http://webmozarts.com/wp-content/uploads/2009/04/profile-form-basic.png" alt="Basic Profile Form" width="442" height="180" /></p>
<p>The idea was to have a user profile form where we can enter the name of the user, his email address and his password and are able to validate a few special conditions. I added a few help texts to enhance the look and usability of the form. Here is the code for the form:</p>
<pre lang="php">// lib/form/doctrine/ProfileForm.class.php
class ProfileForm extends sfFormDoctrine
{
  protected $user = null;

  public function __construct(sfUser $user)
  {
    $this-&gt;user = $user;
  }

  public function configure()
  {
    $this-&gt;addField('name')
         -&gt;setWidgetAttributes(array('max_length' =&gt; 15))
         -&gt;setValidatorOptions(array('max_length' =&gt; 15))
         -&gt;setHelp('Your full name, f.i. "John Travolta"');

    $this-&gt;addField('email')
         -&gt;setValidator(new sfValidatorEmail())
         -&gt;setHelp('A valid email address, f.i. "john.travolta@gmail.com"');

    $this-&gt;addField('password', new PasswordField())
         -&gt;setHelp('Must not be "pulpfiction"');

    $this-&gt;addField('password_again')
         -&gt;setWidget(new sfWidgetPassword())
         -&gt;setValidator(new sfValidatorPass())
         -&gt;setLabel('Password (again)');

    $this-&gt;setFinalValidator(new sfValidatorAnd(
      new sfValidatorCompare('password_again', '==', 'password',
          'The passwords must be equal'),
      new sfValidatorCallback($this, 'comparePasswordAndName')
    ));

    if (!$this-&gt;user-&gt;hasCredential('admin'))
    {
      $this-&gt;getField('name')-&gt;setEditable(false);
    }
  }

  public function comparePasswordAndName(sfValidator $validator, array $values)
  {
    if ($values['name'] == $values['password'])
    {
      throw new sfValidatorError('The password must not be the same as the name',
          'password');
    }
  }
}</pre>
<p>I introduced you to the concept of form fields that bundle a widget and a validator. If you have not read <a href="http://webmozarts.com/2009/04/12/improving-the-forms/" title="Improving the Forms" class="liinternal">the post explaining this concept</a>, I recommend you to read it now, because I will build up on it today.</p>
<h3>Convention Over Configuration</h3>
<p>Many forms in symfony applications share the same type of fields. An email address, for example, is in 95% of the cases a normal input widget with an email validator. Redefining this definition in different forms leads to code duplication, so we should extract it into a separate field type. If we do this for the most common field types, we come up with a nice little collection of fields that should be bundled with symfony by default:</p>
<ul>
<li><code>sfTextField</code> (<code>sfWidgetInput</code>, <code>sfValidatorString</code>)</li>
<li><code>sfTextareaField</code> (<code>sfWidgetTextarea</code>, <code>sfValidatorString</code>)</li>
<li><code>sfPasswordField</code> (<code>sfWidgetInputPassword</code>, <code>sfValidatorString</code>)</li>
<li><code>sfEmailField</code> (<code>sfWidgetInput</code>, <code>sfValidatorEmail</code>)</li>
<li><code>sfCheckboxField</code> (<code>sfWidgetCheckbox</code>, <code>sfValidatorBoolean</code>)</li>
<li><code>sfCountryField</code> (<code>sfWidgetI18nSelectCountry</code>, <code>sfValidatorI18nSelectCountry</code>)</li>
<li><code>sfLanguageField</code> (<code>sfWidgetI18nSelectLanguage</code>, <code>sfValidatorI18nSelectLanguage</code>)</li>
<li><code>sfSelectField</code> (<code>sfWidgetSelect</code>, <code>sfValidatorChoice</code>)</li>
</ul>
<p>I might have forgotten quite a few now, but you see where I am heading. With a decent collection of predefined fields you will only need to manually define widgets and validators in edge cases. This is especially great for beginners who do not have to learn about widgets and validators to create simple forms!</p>
<p>Let&#8217;s look at how we can reduce the above form definition even more by using these predefined fields:</p>
<pre lang="php">  public function configure()
  {
    $this-&gt;addField('name', new sfTextField(15))
         -&gt;setHelp('Your full name, f.i. "John Travolta"');
    $this-&gt;addField('email', new sfEmailField())
         -&gt;setHelp('A valid email address, f.i. "john.travolta@gmail.com"');
    $this-&gt;addField('password', new sfPasswordField())
         -&gt;setHelp('Must not be "pulpfiction"');
    $this-&gt;addField('password_again', new sfPasswordField())
         -&gt;setValidator(new sfValidatorPass())
         -&gt;setLabel('Password (again)');

    $this-&gt;setFinalValidator(new sfValidatorAnd(
      new sfValidatorCompare('password_again', '==', 'password',
          'The passwords must be equal'),
      new sfValidatorCallback($this, 'comparePasswordAndName')
    ));</pre>
<h3>Field Groups</h3>
<p>So far, I have left the question open about how we can bundle the two password fields together, so you can just drop them into any form. The idea to solve this problem is to create field groups <a href="http://blog.vworld.at/2009/04/14/improving-the-forms-even-more/" title="Improving the forms even more. David's virtual world. A blog about symfony and software in general." target="_blank" class="liexternal">as proposed by David</a>.</p>
<p>A field group is simply a collection of fields that logically belong together. These fields may share a common initial and final validator, a common label, a common help text and a few other things. You will see that field groups are very similar to embedded form as they exist right now.</p>
<p class="info">In fact, a form <em>is</em> a field group with a few extra abilities such as CSRF protection, form tag generation etc.</p>
<p>Normal fields and field groups share a common interface. In practice, this means that you can simply add groups by calling <code>addField()</code> and nest groups inside each other. It does also mean that the developer doesn&#8217;t necessarily need to know whether a field is a &#8220;normal&#8221; field or a field group, which is exactly what we will do with the password field.</p>
<p>To understand the implementation, we will look at the common interface <code>sfFormFieldInterface</code> first:</p>
<pre lang="php">interface sfFormFieldInterface
{
  public function bind($taintedValue, $taintedFile);
  public function getData();
  public function getId();
  public function getLabel();
  public function getHelp();
  public function render();
  ...
}</pre>
<p class="info">You may wonder what the methods <code>bind()</code> and <code>getData()</code> do in a form field. To use the real power of object orientation, the bound values are delegated from the form to all nested fields and field groups, where they are validated. The form can collect the cleaned values again by calling <code>getData()</code> on all fields and field groups. Because embedded forms are nothing more than field groups, this implementation also solves the common problem that <code>bind()</code> is not called on embedded forms.</p>
<p>Now we can finally implement our combined password field. The combined field extends <code>sfFormFieldGroup</code> which already implements <code>sfFormFieldInterface</code>, so we only need to configure the field:</p>
<pre lang="php">class VerifiedPasswordField extends sfFormFieldGroup
{
  public function configure()
  {
    $this-&gt;addField('first', new sfPasswordField());
    $this-&gt;addField('second', new sfPasswordField())
         -&gt;setValidator(new sfValidatorPass())
         -&gt;setLabel('Password (again)');

    $this-&gt;setFinalValidator(
      new sfValidatorCompare('second', '==', 'first',
          'The passwords must be equal')
    );
  }
}</pre>
<p>Now we can simply drop our password field into the form:</p>
<pre lang="php">  public function configure()
  {
    $this-&gt;addField('password', new VerifiedPasswordField())
         -&gt;setHelp('Must not be "pulpfiction"');
  }</pre>
<p>Alert readers might have noticed that the password fields are now named &#8220;first&#8221; and &#8220;second&#8221;. Do you wonder how that will be translated into form field names? It works just the same way as it does now for embedded forms: The name of the internal field is appended to the name of the external field in squared brackets (f.i. &#8220;password[first]&#8220;).</p>
<p>Now you probably think that this implementation makes things harder than they were! When processing the values after a successful validation, we need to know that the password is stored in &#8220;password[first]&#8221; instead of simply &#8220;password&#8221;!</p>
<p>Calm down old boy, help is on the way. To find our solution, let&#8217;s look at the output of the method <code>VerifiedPasswordField::getData()</code>, which returns the cleaned values of the field group:</p>
<pre lang="php">// VerifiedPasswordField::getData()
array(
  'first' =&gt; 'The password',
  'second' =&gt; 'The password',
)</pre>
<p>Hm, any idea? Let&#8217;s also look at the output of <code>ProfileForm::getData()</code>.</p>
<pre lang="php">// ProfileForm::getData()
array(
  'name' =&gt; 'The name',
  'email' =&gt; 'thename@gmail.com',
  'password' =&gt; array(
    'first' =&gt; 'The password',
    'second' =&gt; 'The password',
  ),
)</pre>
<p>Did you already find the solution? I&#8217;ll tell you: It&#8217;s fairly easy. We just need to modify <code>getData()</code> in <code>VerifiedPasswordField</code> to just return a single password instead of an array.</p>
<pre lang="php">  public function getData()
  {
    $data = parent::getData();

    return $data['first'];
  }</pre>
<p class="info">Now you probably understand why <code>getData()</code> isn&#8217;t named <code>getValues()</code>, like it is in the forms framework right now. The problem is that <code>getData()</code> can return single values (in simple fields) or arrays (in field groups). Naming the method <code>getValues()</code> would implicate that it always returns an array.</p>
<h3>Time To Relax</h3>
<p>If you made it until here, the hardest part of this post is over. Field groups allow us to easily implement and reuse a set of fields. As you have seen, we can even use field groups as if they were a single field. Especially in large applications, this architecture can hugely simplify your form definitions and reduce duplicate code.</p>
<p>You can, of course, create field groups on the fly, if you want to logically group fields together:</p>
<pre lang="php">  public function configure()
  {
    $group = $this-&gt;addGroup('personal')
          -&gt;setLabel('Personal Information')
          -&gt;setHelp('Please enter your personal information here so we can sell it');
    $group-&gt;addField('first_name')
          -&gt;setLabel('First name');
    $group-&gt;addField('surname');
  }</pre>
<div class="info">Calling</p>
<pre lang="php">$form-&gt;addGroup('groupname')</pre>
<p>without explicitly passing an <code>sfFormFieldGroup</code> instance has the same effect as calling</p>
<pre lang="php">$form-&gt;addGroup('groupname', new sfFormFieldGroup())</pre>
<p>or</p>
<pre lang="php">$form-&gt;addField('groupname', new sfFormFieldGroup())</pre>
</div>
<p>In my next post, I will speak about how formatters and group layouts can help you to reduce duplicate code in your form templates and help you to sustain a uniform look in applications with many forms. You will learn that the structural information stored in field groups can easily be used to generate a visually appealing presentation.</p>
<p>How do you like the field groups? Are there any use cases that cannot be implemented with this architecture?</p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://webmozarts.com/2009/04/19/improving-the-forms-field-groups/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Improving the Forms</title>
		<link>http://webmozarts.com/2009/04/12/improving-the-forms/</link>
		<comments>http://webmozarts.com/2009/04/12/improving-the-forms/#comments</comments>
		<pubDate>Sun, 12 Apr 2009 10:25:21 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Thinking Ahead]]></category>

		<guid isPermaLink="false">http://webmozarts.com/?p=161</guid>
		<description><![CDATA[After my last post about simplifying symfony and especially the forms framework, I started diving into the forms framework to find out how we could improve it. I tried to find ways to improve the usability of this framework without reducing its mighty possibilities. Quite the contrary, I think that the forms can be made [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>After my last <a href="http://webmozarts.com/2009/04/07/no-piece-of-cake/" title="No Piece of Cake" class="liinternal">post about simplifying symfony</a> and especially the forms framework, I started diving into the forms framework to find out how we could improve it. I tried to find ways to improve the usability of this framework without reducing its mighty possibilities. Quite the contrary, I think that the forms can be made even mightier than they are now.<span id="more-161"></span></p>
<div class="note">
<p>The concept presented in this article series is not implemented in symfony. It has been developed together with a few other people in the community. With these articles, I would like to receive feedback about how you like the concept and how it can be improved.</p>
<ol>
<li>Improving the Forms</li>
<li><a href="http://webmozarts.com/2009/04/19/improving-the-forms-field-groups/" title="Adding Field Groups to the Symfony Forms Framework" class="liinternal">Improving the Forms: Field Groups</a></li>
<li><a href="http://webmozarts.com/2009/04/23/improving-the-forms-layouts-and-formatters/" title="Using Layouts to Easily Generate the HTML Code of Symfony Forms" class="liinternal">Improving the Forms: Layouts and Formatters</a></li>
</ol>
</div>
<h3>The Situation</h3>
<p>In my last post I introduced you to the following situation: A form should allow to edit a user’s name, email address and password. The name should only be editable by administrators, while the password should be entered twice to make sure it was entered correctly. The maximum length of the name is 15 characters and the password should not be the same as the name.</p>
<p>We came up with the following class:</p>
<pre lang="php">// lib/form/doctrine/ProfileForm.class.php
class ProfileForm extends sfFormDoctrine
{
  protected $user = null;

  public function __construct(sfUser $user)
  {
    $this-&gt;user = $user;
  }

  public function configure()
  {
    $this-&gt;setWidgets(array(
      'name'           =&gt; new sfWidgetFormInput(array(), array(
        'max_length' =&gt; 15
      ),
      'email'          =&gt; new sfWidgetFormInput(),
      'password'       =&gt; new sfWidgetFormInputPassword(),
      'password_again' =&gt; new sfWidgetFormInputPassword(),
    ));
    $this-&gt;widgetSchema-&gt;setLabel('password_again', 'Password (again)');

    $this-&gt;setValidators(array(
      'name'           =&gt; new sfValidatorString(array(
        'max_length' =&gt; 15
      ), array(
        'max_length' =&gt; 'The name must be 15 characters or longer'
      ),
      'email'          =&gt; new sfValidatorEmail(array(), array(
        'required' =&gt; 'Please enter your email address',
      )),
      'password'       =&gt; new sfValidatorString(array(), array(
        'required' =&gt; 'Please enter a password',
      )),
      'password_again' =&gt; new sfValidatorPass(),
    ));

    // implement custom validation logic
    $this-&gt;validatorSchema-&gt;setPostValidator(new sfValidatorAnd(array(
      new sfValidatorSchemaCompare('password_again', '==', 'password', array(
        'invalid' =&gt; 'The passwords must be equal'
      )),
      new sfValidatorCallback(array(
        'callback' =&gt; array($this, 'comparePasswordAndName')
      )),
    )));

    // only administrators may enter the user name
    if (!$this-&gt;user-&gt;hasCredential('admin'))
    {
      unset($this['name']);
    }
  }

  public function comparePasswordAndName(sfValidator $validator, array $values)
  {
    // if the field "name" is not editable, it does not exist in $values
    if (array_key_exists('name', $values) &amp;&amp; $values['name'] == $values['password'])
    {
      $error = new sfValidatorError($validator,
          'The password must not be the same as the name');

      // throw an error schema so the error appears at the field "password"
      throw new sfValidatorErrorSchema($validator, array('password', $error));
    }
  }
}</pre>
<h3>The Issues</h3>
<p>The above form definition bears several issues:</p>
<ul>
<li>It is not possible to abstract form fields that combine a widget, a validator and possible other settings. You might want to use a password field in several forms so it should be possible to extract that definition into a separate class.</li>
<li>To configure the form, you need to know about the widget schema and the validator schema. You also need to know where to call which method. For instance, you need to call <code>setWidgets()</code> on the form, <code>setLabels()</code> on the widget schema and <code>setPostValidator()</code> on the validator schema.</li>
<li>Nearly none of the default validator error messages like &#8220;Invalid.&#8221; or &#8220;Required.&#8221; are useful in production, thus we always have to configure them. Validators should provide sensible defaults for these errors to reduce the amount of configuration.</li>
<li>Some of the used classes have complex constructor signatures that are hard to remember. <code>sfValidatorCallback</code>, for instance is always called with a callback. It should be possible to pass the callback directly to its constructor without having to create addtional arrays.</li>
<li>If the user is not administrator, the field &#8220;name&#8221; is not available. Because of that we must implement additional checks everytime we access the form values to find out whether the name has been set. But, in fact, the name value should always be there. It just is not always editable.</li>
<li>Throwing a custom validation error and binding it to a specific field is tedious.</li>
</ul>
<p>I was searching for ways to improve these issues and will explain them in more detail below.</p>
<h3>Form Field Abstraction</h3>
<p>It was very useful if you could abstract form fields in symfony that combine a validator, a widget and possible other settings. Let&#8217;s just imagine for this post that <code>sfField</code> is a class that allows bundling a widget and a validator.</p>
<p class="note">I don&#8217;t think that including the &#8220;form&#8221; in the name is necessary (f.i. <code>sfFormField</code>). The &#8220;sf&#8221; prefix is reserved to symfony core classes and I can&#8217;t think of any other context in the core where an <code>sfField</code> class could serve useful. KISS.</p>
<p>To create our custom password field, we would just extend <code>sfField</code> and combine the logic inside.</p>
<pre lang="php">// lib/form/fields/PasswordField.class.php
class PasswordField extends sfField
{
  public function configure()
  {
    $this-&gt;setWidget(new sfWidgetInputPassword());
    $this-&gt;setValidator(new sfValidatorString(array(), array(
      'required' =&gt; 'Please enter a password',
    ));
  }
}</pre>
<p>Great! A neatly decoupled definition of a password field. But how should we add this field to a form? Probably with the most obvious method name there is for this task: <code>addField()</code>.</p>
<pre lang="php">// lib/form/doctrine/ProfileForm.class.php
class ProfileForm
{
  public function configure()
  {
    $this-&gt;addField('password', new PasswordField());
    ...
  }
}</pre>
<p>Can it be easier?</p>
<p class="info">You may ask yourself whether we can&#8217;t just bundle the second field for repeating our password as well. We certainly could, but I&#8217;ll leave the answer for this question to another post.</p>
<h3>Widgets and Validators</h3>
<p>As said before, we currently need to know a lot about the form&#8217;s internals to configure it successfully. We need to know about <code>sfWidgetFormSchema</code>, <code>sfValidatorSchema</code> and <code>sfForm</code> and their respective methods. Couldn&#8217;t we simplify that somewhat?</p>
<p>Let&#8217;s wait for a moment. In the previous section we introduced a new class <code>sfField</code> that bundles a widget, a validator and possible other settings. We also introduced a method <code>addField()</code> that adds a form field to the form.</p>
<p>Now we could <em>return</em> the added field from <code>addField()</code> and allow a modification of its widget, validator, label and other properties in a fluent coding style!</p>
<p>Let&#8217;s look at how the form&#8217;s <code>configure()</code> method looks like with these modifications:</p>
<pre lang="php">  public function configure()
  {
    $this-&gt;addField('name', new sfField())
         -&gt;setWidget(new sfWidgetInput(array(), array('max_length' =&gt; 15)))
         -&gt;setValidator(new sfValidatorString(array('max_length' =&gt; 15)));

    $this-&gt;addField('email', new sfField())
         -&gt;setWidget(new sfWidgetInput())
         -&gt;setValidator(new sfValidatorEmail());

    $this-&gt;addField('password', new PasswordField());

    $this-&gt;addField('password_again', new sfField())
         -&gt;setWidget(new sfWidgetInputPassword())
         -&gt;setValidator(new sfValidatorPass())
         -&gt;setLabel('Password (again)');
    ...
  }</pre>
<p>Doesn&#8217;t look too bad. To reduce the amount of code, <code>addField()</code> could always add an instance of <code>sfField</code>, if no field is given, and preconfigure it with <code>sfWidgetInput</code> and <code>sfValidatorString</code>. Then we could introduce new methods <code>sfField::setWidgetOptions()</code>, <code>sfField::setWidgetAttributes()</code> and <code>sfField::setValidatorOptions()</code> that allow a fluent modification of these properties.</p>
<pre lang="php">  public function configure()
  {
    $this-&gt;addField('name') // implicitly sfWidgetInput and sfValidatorString
         -&gt;setWidgetAttributes(array('max_length' =&gt; 15))
         -&gt;setValidatorOptions(array('max_length' =&gt; 15));

    $this-&gt;addField('email') // implicitly sfWidgetInput
         -&gt;setValidator(new sfValidatorEmail(array(), array(
           'required' =&gt; 'Please enter your email address',
         )));

    $this-&gt;addField('password', new PasswordField());

    $this-&gt;addField('password_again')
         -&gt;setWidget(new sfWidgetInputPassword())
         -&gt;setValidator(new sfValidatorPass())
         -&gt;setLabel('Password (again)');
    ...
  }</pre>
<p>Again our code became a bit easier to read and write. For reference, here is how the configuration of these settings was like before:</p>
<pre lang="php">  // before
  public function configure()
  {
    $this-&gt;setWidgets(array(
      'name'           =&gt; new sfWidgetFormInput(array(), array(
        'max_length' =&gt; 15
      ),
      'email'          =&gt; new sfWidgetFormInput(),
      'password'       =&gt; new sfWidgetFormInputPassword(),
      'password_again' =&gt; new sfWidgetFormInputPassword(),
    ));
    $this-&gt;widgetSchema-&gt;setLabel('password_again', 'Password (again)');

    $this-&gt;setValidators(array(
      'name'           =&gt; new sfValidatorString(array(
        'max_length' =&gt; 15
      ), array(
        'max_length' =&gt; 'The name must be 15 characters or longer'
      ),
      'email'          =&gt; new sfValidatorEmail(array(), array(
        'required' =&gt; 'Please enter your email address',
      )),
      'password'       =&gt; new sfValidatorString(array(), array(
        'required' =&gt; 'Please enter a password',
      )),
      'password_again' =&gt; new sfValidatorPass(),
    ));
    ...
  }</pre>
<h3>Sensible Default Error Messages</h3>
<p>Nearly all default error messages of the validators are absolutely unusable in a production environment. If you listen to the big usability gurus like Jakob Nielsen (see his <a href="http://www.useit.com/alertbox/20010624.html" title="Jakob Nielsen's Error Messages Guidelines" target="_blank" class="liexternal">Error Messages Guidelines</a>), error messages should give &#8220;Constructive advice on how to fix the problem&#8221;. &#8220;Required.&#8221; and &#8220;Invalid.&#8221;, unfortunately, do not.</p>
<p>I think that all validators should be preconfigured with sensible error messages. Examples for the &#8220;required&#8221; and &#8220;invalid&#8221; errors of <code>sfValidatorEmail</code> are &#8220;Please enter an email address&#8221; and &#8220;The given email address is not valid&#8221;.</p>
<p>With sensible default messages, we can yet again reduce the complexity of our code:</p>
<pre lang="php">  public function configure()
  {
    ...
    $this-&gt;addField('email')
         -&gt;setValidator(new sfValidatorEmail());
    ...
  }</pre>
<p>Compared to before:</p>
<pre lang="php">  // before
  public function configure()
  {
    ...
    $this-&gt;addField('email')
         -&gt;setValidator(new sfValidatorEmail(array(), array(
           'required' =&gt; 'Please enter your email address',
         )));
    ...
  }</pre>
<h3>The Post Validator</h3>
<p>Now I&#8217;ll look at how to improve the post validator of our profile form. Basically I think the name is a bit weird. I am familiar with the latin expression &#8220;post&#8221;, but wouldn&#8217;t the english expression &#8220;final&#8221; fit in better?</p>
<p>Let&#8217;s imagine we live in an ideal world where <code>setPostValidator()</code> can be moved to <code>sfForm</code> and renamed to <code>setFinalValidator()</code>.</p>
<pre lang="php">$this-&gt;setFinalValidator(...);</pre>
<p>Okay. Next step: <code>sfValidatorAnd</code> and its contained validators. First of all, I think we could extend <code>sfValidatorAnd</code> to accept an infinite number of arguments <em>or</em> an array containing these arguments. In Java we would achieve this by overloading the method. In PHP we cannot overload methods, but due to the weak typing we can still simulate this behaviour with one method.</p>
<p>There&#8217;s another candidate for simplification: <code>sfValidatorCallback</code>. Let&#8217;s just recall the current usage of this class:</p>
<pre lang="php">new sfValidatorCallback(array('callback' =&gt; array($this, 'comparePasswordAndName')));</pre>
<p>Why is this so complicated? It&#8217;s obvious that we want to pass a callback to this class. A callback can be either a single string or an array with two entries. We can again &#8220;overload&#8221; the constructor to accept either a single argument (a function name) or two arguments (a class or object method).</p>
<pre lang="php">new sfValidatorCallback($this, 'comparePasswordAndName');</pre>
<p>Much better. Last step: <code>sfValidatorSchemaCompare</code>. I think the usage of its constructor is pretty straight-forward. Because I can never remember its name, this validator should be renamed to <code>sfValidatorCompare</code> (KISS). Furthermore it is always necessary to pass an error message to this class, so why not make it the fourth argument?</p>
<pre lang="php">new sfValidatorCompare('password_repeat', '==', 'password',
    'The passwords must match');</pre>
<p>Now we can draw the whole picture of our final validator:</p>
<pre lang="php">    $this-&gt;setFinalValidator(new sfValidatorAnd(
      new sfValidatorCompare('password_repeat', '==', 'password',
          'The passwords must match'),
      new sfValidatorCallback($this, 'comparePasswordAndName')
    ));</pre>
<p>Isn&#8217;t this much nicer to read? Here&#8217;s the old definition again:</p>
<pre lang="php">    // before
    $this-&gt;validatorSchema-&gt;setPostValidator(new sfValidatorAnd(array(
      new sfValidatorSchemaCompare('password_again', '==', 'password', array(
        'invalid' =&gt; 'The passwords must be equal'
      )),
      new sfValidatorCallback(array(
        'callback' =&gt; array($this, 'comparePasswordAndName')
      )),
    )));</pre>
<h3>Editable vs. Non-Editable</h3>
<p>In forms it is very common to display some fields as editable and some fields as non-editable depending on the user&#8217;s rights. Just think of a common article form. The administrator may be able to change the author of an article, while the editor may only be allowed to see the author.</p>
<p>In the past, I have read several times that people would like to set fields to read-only in the admin generator. One such situation was the <a href="http://trac.symfony-project.org/wiki/Symfony12AdminGenerator#SomenotesfromKlemensUllmannklemens_u" title="Discussion in the symfony wiki about new features of the admin generator in symfony 1.2" target="_blank" class="liexternal">discussion about the admin generator for symfony 1.2</a>. Since the admin generator is now based on the forms framework, this would be essentially the same feature.</p>
<p>The idea is to extend the current <code>sfWidgetForm</code> class to have two different states: &#8220;editable&#8221; and &#8220;non-editable&#8221;. Dependent on the state, each widget renders different HTML. Let&#8217;s look at <code>sfWidgetFormInputDate</code> for example. If this widget is editable, it displays the three select fields that we all know. But if the widget is not editable, it renders the date as plain text in the configured culture.</p>
<p class="info">Do you notice something? If such a widget is implemented, it is essentially not a form widget anymore, but just &#8220;a widget&#8221;. In this case we could remove the &#8220;Form&#8221; from its name and reuse the widget in other components, such as <code>sfGrid</code> <img src='http://webmozarts.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<p>Let&#8217;s look at the configuration of our &#8220;name&#8221; field with this new widget concept. Instead of removing the field when the user is not an administrator, we just disable it.</p>
<pre lang="php">    if (!$this-&gt;user-&gt;hasCredential('admin'))
    {
      $this-&gt;getField('name')-&gt;setEditable(false);
    }</pre>
<p>That&#8217;s all! Compared to before:</p>
<pre lang="php">    // before
    if (!$this-&gt;user-&gt;hasCredential('admin'))
    {
      unset($this['name']);
    }</pre>
<p class="note">The form should still populate the &#8220;name&#8221; value after submitting so that we do not have to care about whether the field was editable or not. The submitted value should just be ignored then.</p>
<h3>Throwing Custom Validation Errors</h3>
<p>Let&#8217;s be honest. Throwing custom validation errors is a pain in the ass. You must remember to pass the validator itself to the error, and then you need to construct an <code>sfValidatorErrorSchema</code> just to associate the error with a field.</p>
<p>In my opinion this should be much easier. The only reason why <code>sfValidatorError</code> requires a passed validator is to populate the error message internally. Why don&#8217;t we just pass the error message?</p>
<p>Second, <code>sfValidatorError</code>&#8217;s constructor could simply accept an optional parameter that specifies the field the validator belongs to.</p>
<p>How does that all look like? Let&#8217;s look at our refactored method <code>comparePasswordAndName()</code>:</p>
<pre lang="php">  public function comparePasswordAndName(sfValidator $validator, array $values)
  {
    if ($values['name'] == $values['password'])
    {
      throw new sfValidatorError('The password must not be the same as the name',
          'password');
    }
  }</pre>
<p>Now that was easy! Here&#8217;s the old definition:</p>
<pre lang="php">  // before
  public function comparePasswordAndName(sfValidator $validator, array $values)
  {
    // if the field "name" is not editable, it does not exist in $values
    if (array_key_exists('name', $values) &amp;&amp; $values['name'] == $values['password'])
    {
      $error = new sfValidatorError($validator,
          'The password must not be the same as the name');

      // throw an error schema so the error appears at the field "password"
      throw new sfValidatorErrorSchema($validator, array('password', $error));
    }
  }</pre>
<h3>Conclusion</h3>
<p>I think we don&#8217;t need to drop object oriented concepts to facilitate the use of the forms. The interface of this framework can be easy while remaining completely well-designed and flexible.</p>
<p>Here you can see the complete new form definition. Especially note the shorter widget names.</p>
<pre lang="php">// lib/form/doctrine/ProfileForm.class.php
class ProfileForm extends sfFormDoctrine
{
  protected $user = null;

  public function __construct(sfUser $user)
  {
    $this-&gt;user = $user;
  }

  public function configure()
  {
    $this-&gt;addField('name')
         -&gt;setWidgetAttributes(array('max_length' =&gt; 15))
         -&gt;setValidatorOptions(array('max_length' =&gt; 15));

    $this-&gt;addField('email')
         -&gt;setValidator(new sfValidatorEmail());

    $this-&gt;addField('password', new PasswordField());

    $this-&gt;addField('password_again')
         -&gt;setWidget(new sfWidgetPassword())
         -&gt;setValidator(new sfValidatorPass())
         -&gt;setLabel('Password (again)');

    $this-&gt;setFinalValidator(new sfValidatorAnd(
      new sfValidatorCompare('password_again', '==', 'password',
          'The passwords must be equal'),
      new sfValidatorCallback($this, 'comparePasswordAndName')
    ));

    if (!$this-&gt;user-&gt;hasCredential('admin'))
    {
      $this-&gt;getField('name')-&gt;setEditable(false);
    }
  }

  public function comparePasswordAndName(sfValidator $validator, array $values)
  {
    if ($values['name'] == $values['password'])
    {
      throw new sfValidatorError('The password must not be the same as the name',
          'password');
    }
  }
}</pre>
<p class="note">The above ideas are only very rough and conceptual. I was thinking about how the interface would be ideal from the user&#8217;s point of view without verifying whether it is implementable and, if yes, how. But that&#8217;s a whole different story anyway. Usually, usability should drive implementation, not the other way round.</p>
<p>I did focus this post on this specific <code>ProfileForm</code>. There are several issues with the form framework that remain to be discussed. One example is how to bundle the two password fields and their post validator to be able to just drop them into any form. Another example is the internal processing of embedded forms. But these topics belong entirely to a new post.</p>
<p>How do you like this interface? Has it flaws and how can it be improved?</p>


<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://webmozarts.com/2009/04/12/improving-the-forms/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
	</channel>
</rss>
