Over a million developers have joined DZone.

PHPSpec: BDD for your classes

DZone's Guide to

PHPSpec: BDD for your classes

· Agile Zone
Free Resource

Speed up delivery cycles and improve software quality with TestComplete. Discover the most robust automated testing tool for end-to-end desktop, mobile, and web testing. Try TestComplete Free.

I dived into Behavior-Driven Development a bit of time ago by starting using Behat (the PHP equivalent of Cucumber) on katas and on a PHP enterprise application. But I never tried to apply a specification-first (in TDD, it would be test-first) approach in code instead of in a business-readable language.

Behavior-Driven Development can be seen as an evolution of Test-Driven Development, stricly in its outside-in version and with a refined language. In the case of the tool I'm reviewing today, BDD is implemented with code instead of with textual feature files (e.g. written in Gherkin) like in Behat.

PHPSpec is similar to (or a port of) RSpec, the original BDD Ruby tool. It fills the need for an approach different from the classical xUnit at the class level. This is how I see them:

The usage of BDD for both the application features and the single classes promote the automated-tests-are-the-specification mantra, and the use of examples sets instead of formal mathematical specification.

The suggested workflow, according to Marcello, is to start from user stories and implemented them with BDD outside-in, first by specifying the application behavior with Behat (business readable tests) and then descending into the details of classes with PHPSpec. This is similar to the famous double Red-Green-Refactor cycle of Acceptance Test-Driven Development.

BDD promotes different semantics for your tests specifications:

  • ┬áspecification classes start with Describe instead of ending with Test.
  • The prefix for methods is itShould instead of test.
  • Verification is accomplished through expectations and specifications, instead of with assertion methods. This leads to code that sounds like English.

Many BDD-friendly APIs were retrofitted on existing testing frameworks: for example PHPUnit has an assertThat() method that can be used with matchers to simulate English-like code.

I think that new testing frameworks don't bring us functional innovations: we can do the same things in PHPT, PHPUnit or PHPSpec: instantiate objects, call methods and perform verification on the results. What we gain here is new semantics (thinking of specifications and not of tests) and a better support for an outside-in workflow: starting from higher-level features and descend into classes by maintaining the same language. You'll never write an unneeded class again.

Maybe the advantages of the language are not perceived as much by people who speak (read and write, mostly) English as a foreign language. Code for us is already another language, and we may have speak in code for longer than in English.


So how does PHPSpec work? You extend a base class, like in PHPUnit, and provide conventionally named methods. The methods will be run in isolation and one at the time.

You are provided on your path with a phpspec script to run the tests/specifications. Of course this script loads the needed dependencies so that you don't have to require_once() anything.

Trial run

Here's how to give PHPSpec a look.
The PEAR installation is recommended. At the time of this writing:

pear channel-discover pear.phpspec.net-1.1.0beta
pear install --alldeps phpspec/PHPSpec

You may have to upgrade your pear installation before (pear upgrade).

--alldeps is fundamental as a missing Console_Color will prevent phpspec from running. The 1.1.0-beta suffix is to avoid pear complaining that the package is not stable. I tried the 1.1.1 version but the phpspec script was missing afterwards.

Going from the installation to a running test is a matter of seconds. phpspec targets command line usage, with colors:

Of course the Api you'll use is not familiar. The project probably will need more documentation in the future, but it's normal since we are accustomed to the huge existing coverage of PHPUnit (I wrote an ebook on that.)


You can use Mockery or Phake, PEAR-installable independent Test Double frameworks, in order to produce, well, Test Doubles. There is also an internal implementation in a separate PEAR package, PHPSpec_Mocks; its Api is a bit ugly since it creates doubles via global functions, but it probably will integrate better due to the lack of setup code and its primitives.

Show us some code!

Here it is, my DescribeFizzBuzz.php file.

 * FizzBuzz is a small kata where the goal is developing a simple function,
 * which we partially specify here. The function... well, we'll see if this
 * specification is clear enough for you to instantly understand what it
 * should do.
 * Disclaimer: both the specification and the code are incomplete, for the 
 * purpose of showing all the basic features of PHPSpec.
class DescribeFizzBuzz extends \PHPSpec\Context
    private $fizzbuzz;

    public function before()
        $this->fizzbuzz = new FizzBuzz();

    public function itShouldReturnTheSameNumberForOrdinaryNumbers()
        $result = $this->spec($this->fizzbuzz->say(2));

    public function itShouldNotReturnTheSameNumberForMultiplesOf3()
        $result = $this->spec($this->fizzbuzz->say(3));

    public function itShouldBeAnObject()

    public function itShouldNotReturnTheSameNumberForMultiplesOf5()
        $this->pending('Buzz implementation needed.');

    public function itShouldReturnBangForMultiplesOf7()
        $this->fail('This scenario should already be specified.');

class FizzBuzz
    public function say($number)
        if ($number % 3 == 0) {
            return 'Fizz';
        return $number;

If you want more, checkout Marcello's presentation.

Release quality software faster with TestComplete. Discover how to decrease testing times and expand test coverage with the most robust automated UI testing tool. Try free for 30 days.


Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}