Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Building a BDD Framework with PHP

DZone's Guide to

Building a BDD Framework with PHP

· DevOps Zone
Free Resource

Planning to extract out a few microservices from your monolith? Read this free guide to learn the best practice before you get started.

Have you heard of Jasmine, the BDD framework for JavaScript? Over the holidays I was looking for something like that for PHP but I couldn’t find anything similar (please let me know if I’m wrong) . (Now I know of a few of them thanks to Dave’s comment.) Because of that, and as an exercise, I hacked together something similar in PHP.

I wanted to write as little code as I could (since it’s only a proof of concept), so I reused the assertion framework or PHPUnit. As I’ve seen when studying Behat, we can use the assertion part for standalone functions. We only need to include the 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 can also use something similar to 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 a 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 that this library is a proof of concept. There’re a lot of things remaining. What do you think?

Source code at GitHub

Measure the impact of feature releases, and of your DevOps program more broadly with full stack experimentation. Learn how with this free article from CITO Research, provided by Split Software.

Topics:

Published at DZone with permission of Gonzalo Ayuso, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}