Thursday, October 08, 2009

Unit testing view helpers

The architecture of the Zend Framework, one of the most popular php frameworks, is very extensible and presents a lot of hooks for subclassing and new implementations. The problem which arises from time to time is the testability of the components produced: view helpers are an example of problematic testing and here I will write about solutions for unit testing them.

View helpers are a key point of the Mvc implementation in Zend Framework, along with the Zend_Controller component. The responsibility of view helpers is to keep programming logic out of the view scripts, which are rendered by the view object. We are talking about the presentational layer: every big of logic kept in a view helper can be reused in other scripts.
View helpers are instantiated on the fly by the view object (a Zend_View instance, or another Zend_View_Interface implementation) and kept there. This object will then include the scripts in a method, providing access to its scope to call fake methods with the name of view helpers (a __call() implementation). Since the scope of the object provides the $this handler, view scripts reference it to call view helpers:
<?php
echo $this->doctype();
?>
<html>
...
This script takes advantage of the Doctype view helper (a Zend_View_Helper_Doctype instance) to produce an html doctype declaration.
You can also write your own view helpers: according to the manual, they should provide an empty constructor to allow instantiation by the view object and a method which name corresponds to the class base name. For instance doctype() is the strategy method of Zend_View_Helper_Doctype.
The view helper class should implement Zend_View_Helper_Interface, which has the only injection point in this architecture, the setView() method.

The empty constructor is the problem in view helper management, since it gets in the way of simple test code when you write view helpers that make use of other view helpers as collaborators. For instance, I wrote yesterday a IconLoader helper which use the standard HeadStyle one to add css rules to the page.
The injection point which I was talking about, the setView() method, is called after instantiation. Once my IconLoader helper is instantiated, the view object injects itself in the helper using this method, providing a reference to other helpers.
In this design, the view acts as a Service Locator, and we have no idea which helpers could be called by another one: every helper class could depend on everything else.
Unit testing prescribes to test the helper class in isolation, substituting the collaborators with mocks or stubs. We have to put in test doubles as collaborators, otherwise we are testing more than one helper at the time and if the test fails we cannot tell if the problem is in the SUT (IconLoader) or in the referenced helpers (HeadStyle, ...). Note that collaborators can reference more collaborators, and soon IconLoader class can depend on the entire framework.

My very-simple-testing solution would be require helpers to specify their collaborators in the constructor or via setters, implementing Dependency Injection. We cannot change the standard Zend Framework architecture, though, but it's not a framework's fault. This solution would have required to build a small automatic dependency injection system, which is not in the scope of Zend Framework 1.x (but will be in 2.x as far as I know).

With the current architecture, we can make different choices to simplify testing (remember an helper's constructor must not have parameters, and we must test our components in isolation):
  • Use the real view object and the real view helpers as collaborators. This is integration testing, and failures on the collaborators or view object or what else they refer to will make my main test fail too. Moreover, at every test you should bootstrap all the Zend Framework's Mvc system, so it's not a viable solution.
  • Providing setters for collaborators. The view object cannot call these setters for us, so in the bootstrap we should require the view helper from the already set up view object and call the setters with the mandatory collaborators. In my example, I would have created a My_Helper_IconLoader::setHeadStyle() method. This is the simplest solution for testability, since we have only to call setters in the test for IconLoader view helper and passing in mocks; however, it requires to instantiate all view helpers which need collaborators at every page request, so it's a bit heavy but mandatory if the collaborators are not view helpers but other complex service classes. Starting to mock collaborators is right, though.
  • Mocking the view object/Service Locator with phpunit. This can be done for one view helper, by setting an expectation on a (mocked too) view object __call() method. But when using multiple helpers as collaborator, phpunit cannot distinguish between calls with different parameters and decide which collaborator helper to return. It's an hack which would not work very well.
  • Provide a Fake view object. This is my choice: write once a fake view class, which implements Zend_View_Interface but instead of creating view helpers only returns the ones set at construction time. The definition of a fake object is a class with a running implementation, but different from the production one, often a simplified implementation used for testing.
With my fake view object, the testing phase becomes very simple. In my setUp() method I have:
    $this->_headStyleMock = $this->getMock('Zend_View_Helper_HeadStyle', array('appendStyle'));
    $view = new View();
    $view->setHelper('headStyle', $this->_headStyleMock);
    $this->_helper = new IconLoader();
    $this->_helper->setView($view);
and after this injection, I can set expectations on $this->_headStyleMock and exercise IconLoader in the test methods.
You can find the View fake class at:
http://nakedphp.svn.sourceforge.net/viewvc/nakedphp/trunk/tests/NakedPhp/Stubs/View.php?revision=52&view=markup
along with some tests on it, which could help you grasp its usage:
http://nakedphp.svn.sourceforge.net/viewvc/nakedphp/trunk/tests/NakedPhp/Stubs/ViewTest.php?revision=52&view=markup
Obviously this fake class was Test-Driven Developed.



Feel free to ask any questions. I care about (unit) testability and using extensively frameworks can often make difficult the TDDer life.

Wednesday, October 07, 2009

Modern database models

The word database is often heard during a developer's education and a decent database knowlege is considered fundamental. Nearly every serious application relies on a database to work and although nowadays the usual choice is a relational database, understanding other models helps to explore new ways of dealing with data and new, emergent products.

The database word indicates the collection of data saved somewhere in the infrastructure: this blog saves posts in a database, Firefox saves preferences in a little database in your filesystem. When we are talking of MySQL and Sql server, the correct term is Database Management System, or DBMS. A DBMS provides all the procedures and libraries needed to access and modify the database content, abstracting away the need to use low-level filesystem functions.
The abstraction a dbms builds upon its storage engine is called model. There is more than one model for representing data: some have become obsolete and other ones are so widely used that they probably will never disappear in the next twenty years no matter what happens in the database scenario.
Let's start talking about database model. The models I am presenting here are logical models, which specify how information is presented to the user or to the application which talks to the database. This model must be distinguished from the physical model, which consists in the way the dbms chooses to persist data on disks, tapes and other mass memory devices.

Flat model
When you open a spreadsheet or a simple ini file, you are using a flat model. Data are organized in one list or table, with similar elements or rows.
The problem with a flat database is representing the relationships between elements. For instance how do you associate two users that are friends or a user with the groups he chooses to belong to? Although this limitations, flat files and databases are useful because of their data access simplicity where there is the need for lightweight and easily implementable systems, such as config files or spreadsheet saved in the comma-separated values format.

Hierarchical model

The first improvement to the flat model, applied for the first time in the 1960s, is the addition of a pointer to every instance of data (which is called record). This pointer establish a child-parent relationship towards another record, where every one of them has at most one parent.
Information is thus presented in a tree structure, which is a good model for many real world entities. For instance, you can represent too much things in Xml, which is a hierarchical model too. The Dns system and Ldap protocol present a hierarchical model, but they are a specific application of this paradigm and not a dbms-like product.
A variation of the hierarchical model is named network model, which removes the limit of one parent and places a set of many pointers into every record. The tree-like model becomes a graph. This concept dates back to the 1965, so there's no buzz around network models and hierarchical general-purpose databases.

Relational model
The relational model is the widely used one which I was referring to at the start of this post. Relational dbms like MySQL, Microsoft SQL Server, PostgreSQL and even Sqlite constitute the majority of today's applications storage mechanisms.
The relational model describes data in various tables, where each row has a fixed set of fields that form the table's columns. Continuing with our example, a User and a Group tables, with their fields lists, are a relational model.
In this model, relationships between entities are established with the equality of some columns, often named primary keys and foreign keys. If you have not previously lived under a rock, you probably have used these databases a lot so I won't bore you anymore.

Object model
This is when the problem becomes interesting. Data that were presented in a relational model yesterday is being substituted by an object model, built with classes and instances. Maintaining the whole object graph in memory is usually too expensive to be feasible, since it requires enormous amount of resources like memory and cpu cycles to search objects in the mess of a 2-million-objects graph.
To preserve the object model and persists data at the same time, various solution have been proposed in the years:
  • Serialize the objects and put the binary stream on disk. Simple, but how do you search a User instance by his nick when he signs in?
  • Mapping the objects to a relational database, more or less saving every object as a row of a table which corresponds to the class of choice. An Object-Relational Mapper is the tool used for these operations, but it has some limits, for instance in dealing with class inheritance; these limits are known as the impedance mismatch. The Orm is also used for retrieval, ideally abstracting away the relational storage from the application.
  • Put the objects in an object database.
So, an object database is a tool built from scratch to persist an object model and to allow retrieval of small parts of the overall graph with procedures similar to the relational one (ordering, selection).
An object database would be great to use in real world, but currently going the Orm route is the standard since relational databases are at the world's center. Data typically don't fall from the sky, and there is a need for synchronization between applications and machines in a relational database. Thus, different object models can work on the same data and even with applications which don't use an object-oriented paradigm.

Document model
Instead of presenting a fixed structure, a dbms can instead show a semi-structured model, where records have no enforced lists of attributes. These type of entities are called documents, and an application or middleware which relies on it can store nearly everything as a document property: the advantage of this technique is that you'll never have to update a schema. An example of a document-oriented, open source database is CouchDB.

The schema-less novelty is one of the last buzzword in the database world, and it's still not clear what will the future of these solutions be. Relational databases are probably here to stay as there is a lock-in from applications all over the world to their data model. Object and document models are often presented as a panacea to improve scalability and simplicity, but they are not a standard at the moment. Try to explore new persistence solution, as the technology changing pace is slow in this field, but it exists.

In the image at the top, a typical relational model for an employees table, with the specification of primary key, fields and foreign keys.

Tuesday, October 06, 2009

Getters and setters in vim

While writing an entity class, it's likely you have to manually write a bunch of methods to modify the state of the object, such as setName(), getName(), setDescription(), etc... It is very simple to setup vim, the powerful editor, for setters and getters prototyping, allowing you to tweak them after the one-time generation to add constraints on the parameters and docblock annotations. The boilerplate code for getters and setters can be very boring to write and this tutorial can save you quite some time if you invest a little in setting up this system.
In this how-to I will cover the php case, but feel free to change the template code for the language you want to use.

Disclaimer: I am not suggesting every class should have getters and setters; quite the contrary. In my opinion only certain classes whose responsibility is to maintain state should have these kind of methods, while stateless services should have no getters and no setters as their collaborators are wired in the constructor.

Step 1: vim snippets system
The first step to perform is downloading snippetsEmu, the set of vim scripts which provides support for snippet management. snippy_plugin.vba contains the plugin, while the package snippy_bundles.vba consists in out-of-the-box snippets for various languages, from php to python and C.
The workflow with this plugin is straightforward: you type a keyword for the snippet you want to use (for instance "for" or "if") while in Insert mode, and press Tab. Then the template code is inserted and you are asked to insert the variables of this template, filling in the blanks and pressing tab after each specification. Variables consist in identifiers and of every piece of code that cannot be predetermined too.
For instance, once the system is in place, to create a for construct you would type:
for<tab>i<tab>1<tab>10<tab>doSomething();<tab>
and the result will be:
for ( $i=1; $i < 10; $i++ )
{ 
doSometing();
}
Obviously you can tweak the template of the for snippet to accomodate your coding standard. It's simpler to try it than to explain it.
The installation is a quick process: open the downloaded .vba file with vim and type
:source %
while in Command mode. The vimball system will install the scripts in your .vim directory.

Step 2: setting up .vimrc
Now we need to include the scripts and define the getters/setters template every time vim is started. To do this, we can use the .vimrc hidden file in your home directory, which is read at vim's startup and whose commands are executed as if they were typed in vim Command mode.
These are the lines you need to add to .vimrc for php getters and setters support:
set tabstop=4
set shiftwidth=4
set expandtab
set autoindent
setlocal comments=sr:/*,mb:*,ex:*/
setlocal fo=cqort
source ~/.vim/plugin/snippetsEmu.vim
source ~/.vim/after/ftplugin/php_snippets.vim
exec "Snippet getset /**<CR>@return ".st."Type".et."<CR>/<CR>public function get".st."Name".et."()<CR>{<CR><Tab>return $this->_".st."name".et.";<CR><BS><BS><BS><BS>}<CR><CR>public function set".st."Name".et."($".st."name".et.")<CR>{<CR><Tab>$this->_".st."name".et." = $".st."name".et.";<CR><BS><BS><BS><BS>}<CR>"

The first lines tell vim to use the tab expansion and replacing all tabs with four spaces as said in the Zend Framework coding standard, which is my style of choice for php development. Other settings include auto indentation of lines and auto generation of * in case a docblock comment new line is created. You may want to not use these settings, but you'll have to edit the snippet line accordingly.
The two source commands import the plugin and the php snippets respectively. The second import is necessary to define the shortcuts st and et (start tag and end tag) used in snippets definition.
The last line set up a template for a snippet named getset. To use it, open vim and go to the line where you want to put the couple of methods getSomething() and setSomething(). Then go in Insert mode and type getset<Tab> and compile the various parts of the template, pressing tab after every template variable insertion. Note that you need to define a variable only once, which will be substituted in every place where it appears.
Again, feel free to adapt the snippet to your programming language and coding style. Note that there are no new lines in the template: they are inserted with the <CR> command which simulates the pression of the Enter key. The definition must be kept on one line.

I hope this tip can speed you up while writing boring getters and setters code. If you decide to create new useful snippets, let me know in the comments.

Monday, October 05, 2009

Readable code is not for maintenance only

Emphasis is often put on writing readable code, for the sake of maintenance. But you forget and reread code every minute, not in 2016, so why worrying about the far future when you should worry about tomorrow?

Long term maintenance issues
Even your code, after six months, becomes a stranger to you. Especially if you have improved your coding skills meanwhile, the implementation will be very hard to grasp at a glance. While it can be possible and recommendable to study and remember a software system's big picture, code at the low level inside public and private methods it's quickly forgotten: variable names and the general flow have to be analyzed again and again. To put is simply the human mind does not have the capability of memorizing every single line of code and implementation decision.
Though, there are some things a developer usually masters in his mind:
  • The general design of the system, as most new features require a knowledge of it to know which component should accomodate new classes and functions.
  • The Api of a widely utilized subsystems or class, like Zend_Form in php or the Collection interface in Java.
These are elements of the implementation which do not change very often, and that are refreshed in the developer's memory nearly every day. Usually there is powerful documentation on these arguments, but having a mental understanding of them is always more beneficial.
For the rest of the project, a typical programmer has only a mental model of how the entire system works, abstracted away from details like methods signatures and Uml sequence diagrams.
This is not a bad thing: human memory is less stressed and the code becomes the last, most refined step of the design. There is no need to study or document the details if the code is well written, and they change so often that keeping memory or documents in synchronization with the code is likely to be impossible. That's why Api documentation is automatically generated nowadays.
In this vision, encapsulation and decoupling are very important from the maintenance point of view not only for the isolation of changes in the code, but also for the use of developers time. If adding a feature or fixing a bug requires the analization of two or three classes, the developer will finish the job earlier than having to modify method signatures over a dozen of them. OCP strives for only adding new code, but you probably still have to read the old one even if you do not modify it: to subclass, to write a new implementation or to override a method you must know the original signatures and contract.
Moreover, meaningful variables, methods and parameters names aid the developer who has to deal with the code in his forced rapid study of the business logic. Everything you cannot remember has to be learned again and again and the faster this relearning process is, the faster the overall development will be.

Short term development issues
The trouble with the current readable code tips is the starting reason: helping maintainers because six months from now you will have forgotten everything about what you have written today. But if you shorten the time interval, the productivity boost given by readable and well-factored code is still valid: all the advantages discussed for maintenance can be applied in development as well, since maintenance is only deferred development.
No feature is integrated in a single pass: this is particulary stressed in the iteration-based methodologies, but it applies to many low level coding activities. TDD, for instance, prescribes to add a test at the time for the class under development, and to make it pass before repeating the cycle. Being the testing automatic or manual, I bet you start from a simplification of the feature and then refine the details: when you build a blog, first you add the article publishing form, then the visualization of posts, the search, a comment system. You can refine even further by adding new fields to the article model: date and time, tags, author. The process involves going back on the same code continuosly.
What activities do you carry out when making a new test pass? What do you do every single time before writing a single line of code?
You go back to the class you're writing and read again the code you have written yesterday, or two minutes ago to pass the test before. And if you do not have a photographic memory, you don't remember every character you wrote. You have to read it. The majority of the software developers in the world neither have such a memory.
Starting to write descriptive code helps your productivity now. If you do not believe it, try to program some serious application in assembly using (computer) memory addresses instead of variable names. You'll find yourself going back and forth in the source to copy addresses as if they were bad chosen variable names, confusing them continuosly.

Code is written one time, and then it is refactored or rewritten, which I see as a new writing process. It is read thousands of times instead. So what you focus on? Code that is short to write with three-characters identifiers or code that is simple to read?

What does the code in the picture do? I don't know. Even if I wrote it yesterday.

Saturday, October 03, 2009

The Swiss Army knife Programmer

MacGyver was unlike secret agents in other television series and films because, instead of relying on high-tech weapons and tools, he carried only a Swiss Army knife and duct tape.
[Wikipedia, MacGyver page]

After the infinite series of Duct Tape Programmer articles that has been populating my Google Reader last week, I've decided to write about a similar class of programmer who you surely know some instance of.
Just like MacGyver, the Swiss Army knife programmer carries his preferred tool along with a stock of duct tape, which as Joel says represents the using large amounts of duct tape to keep together the pieces of an application mindset.
Armed with his tool, which contains screwdrivers, a can opener, a magnifying glass, an altimeter and an mp3 player, the SAK programmer goes on and on and uses it for every task he has to do. When he has a new business idea, it involves the use of his tool to conquer the world. When he has to carry out a boring, obvious task, he tries to squeeze in his tool in some way.

Practically speaking the equivalent of Swiss Army knife is a programming language or particular technology which is overused, in applications where it is out of scope. A big toolbox is better than a Swiss Army knife if you know how to use all the tools contained instead of carrying a small one which promises to do everything you need.
These are examples of Swiss Army Knife cases:
  • using php for gtk applications. The php gtk extension, which contains the bindings for the gtk graphic library, is an edge project which provides the capability for php to build desktop applications with windows and buttons on the machine where it is run. Certainly the developers of this extension are having a lot of fun taking php to its edge, but php is a language where the interpreter comes with a default max_execution_time directive set to 30 seconds. I don't think the core developers were thinking of a php script which runs for hours when designing the engine.
  • usage of IDEs in every situation, when a bit of command line fu can solve problems efficiently and quickly. NetBeans and Eclipse try to provide every feature a developer needs in a single application, also via plugins: this resembles a overloaded knife. NetBeans here is a bit better then Eclipse in the sense that it takes avdantage of command line applications like svn.
  • the opposite overusage of command line fu when opening a text editor and doing a find&replace is enough.
  • Google Chrome operating system, which relies on web based applications only. Cloud computing is great and I strongly believe web applications are the next big thing: Gmail is proving it every day. But these kind of apps are probably not capable, at the moment, to replace every binary on your machine. Try to edit a video via web.
  • Design patterns are great standard solutions for object-oriented languages pitfalls, but their overusage can plague a code base. Factories (for entities) and above all Singletons can and should be limited to the cases where they provide real value.
  • I once fell in love with the Dojo grid and I tried to use it for every management application I could think of. It can be a serious issue if you are unaware of being a Swiss Army knife programmer on certain technologies, when you find yourself as an advocate in a religion war.
There are very few general-purpose technologies that can be used in nearly any project, and they are usually built from scratch to solve analogue and generic project management issues:
  • Subversion and other source control systems work well in many situations. As the name says, source code files were the original subject of version control, but Git and Subversion have expanded their dominion on wiki formatted documentation, xml configuration files and plain text. A common suggestion is  to put everything you cannot build under source control (and this leaves out binaries, fortunately).
  • Trac and Bugzilla can be used for every software project. Though, their scope is limited to software project management and for instance a novel developed with the help of Trac is a strange thing (unless it is written from a group of authors who need a communication tool). The power of such software is in facilitating communication between developers and usage from a single user is likely to be an overkill.
The power of open source applications resides in the reuse of code and libraries and even of entire projects in incredibly different fields, like in Subversion's case. But before stretching a technology over its limits, think if you are really using the right tool for the job.

Not so strangely, searching "the right tool for the job" on Google shows the first result is "Lisp is the best tool for large (and small!) projects."

Friday, October 02, 2009

Practical testing in php part 9: command line options

This is the ninth and last part of the php testing series. If you liked it, you should subscribe to the feed to check out similar articles in the future.

Optimizing a test suite by adding test methods and test cases can be useful to improve the quality of your application code. Yet, every optimization starts with a profiling phase, that tells you where there is a need for test cases and where there is already a good coverage.
Code coverage is defined as the ratio of lines of code exercised by the unit tests to the overall number of lines; the same ratio can be calculated using code blocks as the unit of measure.
Phpunit provides code coverage reports generation via command line switches: one of them is --coverage-html $directory which places a human-readable html report in the $directory specified. There are other formats available, such as Xml, created for the purpose of interpreting a report with a third party application.
Please note that phpunit code coverage features require the xdebug extension to work.

Another useful switch is the --configuration $file one. $file should be an xml configuration file that tells phpunit what files have to be considered as containing test cases. This is very handy to compose a suite and can substitute the famous and hard to mantain AllTests.php files.
Here is a simple example for a configuration file:
<phpunit>
    <testsuite name="Ossigeno Test Suite">
        <directory suffix="Test.php">tests/</directory>
        <directory suffix="Test.php">application/modules</directory>
    </testsuite>
</phpunit>
Running phpunit with this switch, instead of specifying a particular file, will force the runner to consider all php files which name ends in "Test.php" in the directories tests/ and application/modules/. While running a single test case gives as output a line of dots, running all these tests in sequence will result in multiple lines and in a list of all failed tests (although you can require the list of skipped and incomplete tests by using the --verbose switch) in the overall list generated according to the configuration.

Along with the --configuration option, I strongly suggest to use the --bootstrap $phpScript directive. Your test cases probably need a global bootstrap phase for autoloading and setting up the include_path or other options. In some old versions of phpunit, you had to include a require_once() call at the start of each test script to make sure it was executed before the test. Now you can simply tell phpunit to run a file of your choice before starting with the test phase.

Running an entire suite is a good practice to discover if your changes or refactorings have broken some functionalities. However, it's an overkill if you have to do it very often, like in a short feedback cycle for TDD: supposing you have more than one test case for your SUT, it can be useful to select all those tests and leaving out the rest of the suite.
This is the case when the @group annotation is handy. You can mark with the @group $name annotation the docblock of test case classes, and also add multiple lines if you feel the contained tests can be useful in more than one scenario. Then the --group $group command line switch excludes test cases which do not belong to $group from being run.

So we can finally give an example of running a test suite:
phpunit --bootstrap tests/TestHelper.php --configuration=tests/configuration.xml
for instance we can restrict the selected tests to the NakedPhp_Form package ones:
phpunit --bootstrap tests/TestHelper.php --configuration=tests/configuration.xml --group=NakedPhp_Form
or requiring a code coverage report to see where we need to add test code:
phpunit --bootstrap tests/TestHelper.php --configuration=tests/configuration.xml --coverage-html directory/

I hope these tips will be useful to you for utilizing phpunit at its best. It is a very well-crafted tool that you can take advantage of for TDD purposes, and also for functional and integration tests. Although the name suggests unit testing as a goal, you should certainly include in your test suite some functional tests, which exercise a feature provided of more than one object, and integration tests, which covers the wiring of your object and verify that your application works on an end-to-end basis.

Bonus tip: using --no-globals-backup and --no-static-backup can speed up your tests execution by avoiding unuseful isolation of tests. If your application has no global state they will work correctly anyway.
If you liked this testing series, you should subscribe to the feed to be informed of new articles on software development and php.

Thursday, October 01, 2009

Practical testing in php part 8: mocks

This is the eighth part of the php testing series. You may want to check out the previous parts or subscribe to the feed for being updated on new articles.

In the last part of this series, we have listed the various types of Test Doubles along with the ones that phpunit can easily generate: Stubs and Mocks. The latter are utilized in a different kind of testing than the one presented so far: behavior verification.

The behavior verification testing style differs from the state verification one in the subjects of the assertion methods. While state verification specifies explicit assertion methods to be called upon a test result, behavior verification is focused on checking the actions the system under test undertakes. These actions comprehend which methods it calls, and how many times it does so; but also the parameters it passes to these methods and their order.
The standard interaction with collaborators in object-oriented systems consists of method calls. This kind of testing prescribes to place assertions directly in the overridden methods of Test Doubles, or at the end of every test, to verify that the SUT behavior conforms to specifical rules. These Test Doubles, which can run assertions on their methods parameters, are called Mock Objects (or simply Mocks). The contraposition here is with Stubs, which extend the capabilities of a state based testing but do not make any assumption on method calls or parameters.
Note that the assertions on parameters are placed inside the generated methods, while assertions on method calls are executed by phpunit after the test has run. This means that in a pure behavior verification test you won't find any assert*() calls, which perform state verification.

Now we are going to rewrite the unit test of the previous part taking advantage of phpunit mocks generation, but with a mixed approach which contains also explicit  assertions. The test was about verifying that the GeolocationService class made use of a GoogleMaps collaborator to find out the latitude and longitude of an User object, and the key characteristic was insulation of the test from the GoogleMaps real implementation with a Test Double. You can find the Stub example here.
class GeolocationServiceWithMocksTest extends PHPUnit_Framework_TestCase
{
    public function testProvidesLatitudeAndLongitudeForAnUser()
    {
        $coordinates = array('latitude' => '42N', 'longitude' => '12E');
        $googleMapsMock = $this->getMock('GoogleMaps', array('getLatitudeAndLongitude'));
        $googleMapsMock->expects($this->once())
                       ->method('getLatitudeAndLongitude')
                       ->with('Rome')
                       ->will($this->returnValue($coordinates));
        $service = new GeolocationService($googleMapsMock);
        $user = new User;
        $user->location = 'Rome';
        $service->locate($user);
        $this->assertEquals('42N', $user->latitude);
        $this->assertEquals('12E', $user->longitude);
    }
}
The test is actually very similar to the Stub one, but there are some differences:
  • the expect() method of the mock returns an expectation object with a fluent interface we can work with. However, this time a matcher is passed which specifies how many times the mocked method should be called. In the Stub example, the matcher used is $this->any(), that does not run any assertions on the number of calls at the end of the test. Other available matchers are $this->never() and $this->exactly($number). The power of the matchers used in xUnit frameworks is they augment the test's code readability, making it similar to plain English.
  • On the expectation object, along with will() and method(), we are also calling with() to specify the parameter we want to check as passed to getLatitudeAndLongitude(). If we wanted to check more parameters as exact values, we would pass an array to with() containing the actual list. However, we can make also weak assertions by using constraints objects, like $this->attributeEqualTo($name, $value) or $this->isInstanceOf($className), or maybe $this->anything() if no assertion has to be made on a particular parameter.
  • There is no formal definition that says Mocks can't return canned results, as this is often mandatory for the code flow and to complete the test successfully. Though, if you TDD the system under test using mocks without predefined results, it's likely that you will produce a class with a different programming style which works with those tests, and uses mocks very effectively.
  • Whenever you write a with() call or a matcher in expects(), be aware you are building a Mock and not a Stub.
You can find the complete, running test case here on pastebin. I tried to include complete examples in this series to show the practical side of testing instead of tips which are great in theory, but fail to apply in a real situation.

After this example of behavior verification, which makes use of the most advanced phpunit features, we are ready to explore the code coverage features in the next part.

You may want to subscribe to the feed to be updated when new articles in this series are available.

Featured post

A map metaphor for architectural diagrams

It is a (two-dimension) representation of a pipe. The map is not the territory , but in software engineering terms they are models of it....

Popular posts