Building a BDD framework with PHP

Do you know Jasmine, the BDD framework for JavaScript? This holidays I was looking for something like that in PHP and I didn’t found anything similar (please let me know if I’m wrong) (now I know a few of them thanks to Dave’s comment) . Because of that, and as an exercise, I hack a little bit building something similar for PHP.

I want to write as less code as I can (it’s only a proof of concept), so I will reuse the assertion framework or PHPUnit. As I’ve seen when studying Behat, we can use the assertion part as standalone functions. We only need to include vendor/phpunit/phpunit/PHPUnit/Framework/Assert/Functions.php file

Here you can see one example.

class StringCalculator
    public function add($string)
        return (int)array_sum(explode(",", $string));

$stringCalculator = new StringCalculator;

describe("add mull returns zero", function () use ($stringCalculator) {
        assertEquals(null, $stringCalculator->add(""));

describe("1,1 should return 2", function () use ($stringCalculator) {
        assertEquals(2, $stringCalculator->add("1,1"));

We also can use something similar than DataProvider in PHPUnit:

describe("add number returns number", function ($expected, $actual, $message) use ($stringCalculator) {
        assertEquals($expected, $stringCalculator->add($actual), $message);
    }, [
        ['expected' => 1, 'actual' => "1", 'message' => 'add 1'],
        ['expected' => 2, 'actual' => "2", 'message' => 'add 1'],
        ['expected' => 10, 'actual' => "10", 'message' => 'add 10'],

And if we need mocks we can use Mockery, for example:

class Temperature

    public function __construct($service)
        $this->_service = $service;

    public function average()
        $total = 0;
        for ($i=0;$i<3;$i++) {
            $total += $this->_service->readTemp();
        return $total/3;

$service = m::mock('service');

describe("testing mocks with mockery", function() use ($service) {
        $service->shouldReceive('readTemp')->andReturn(11, 12, 13);
        $temperature = new Temperature($service);
        assertEquals(12, $temperature->average(), "dummy message");

I’ve created an small console application to run the test suites using symfony/console and symfony/finder components. We can run it with:

php ./bin/console.php texter:run ./tests

Beware because this library is a proof of concept. There’re a lot of remaining things. What do you think?

Source code at github

About Gonzalo Ayuso

Web Architect. PHP, Python, Node, Angular, ionic, PostgreSQL, Linux, ... Always learning.

Posted on August 19, 2013, in php, PHPUnit, Symfony, Technology and tagged , , , , , . Bookmark the permalink. 11 Comments.

  1. There are quite a few out there, here’s the ones I can remember: (my own)

  2. cool! Thanks. I will study them

  3. i am surprised you don’t know about phpspec/phpspec
    it is the defacto, that is it 😉

    • phpspec wasn’t the thing that I had in mind. I was thinking about something like describe(‘name of the test with spaces’, function())
      (the idea behind Jasmine) phpspec is something different (is a bdd toolkit, but different) such as behat.

      (I also must admit that I wanted to play with closures 🙂 )

  4. Thank you for the article!
    Also have a look at Codeception – really outstanding tool

  5. Hi, I started my own implementation too 🙂 To not do all the stuff ( and probably you don’t want to implement JUnit reporting, HTML reporting, events, filters, groups, etc) I made this as very tiny addon on top of PHPUnit. I was inspired by minitest, in which you can use both syntax modes: BDD and classical TDD.

    also assertions

    I think the only way to get it done with all features, is using PHPUnit on top.

  1. Pingback: Дайджест интересных новостей и материалов из мира PHP за последние две недели №24 (11.08.2013 — 25.08.2013) | Juds

  2. Pingback: PHP Digest №1 ( 11.08.2013 — 25.08.2013 ) | FASIGN Blog

Leave a Reply to Gonzalo Ayuso Cancel reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: