Today, we are implementing the MageTest/MageSpec Module based on PHPSpec toolset.
In this implementation, we have two different tests taken from the Magecasts tutorials. The first one is to understand how PHPSpec works.
First Test
“We will look at PHPspec and how we can use it to enhance our development workflow”.
Prerequisites
PHP 5.3.x or greater
Install composer
Getting Started
Create composer.json file
On root project, create composer.json file with the data below:
[ecko_code_highlight language=”javascript”]
{
“require-dev”: {
“phpspec/phpspec”: “~2.1”
},
“config”: {
“bin-dir”: “bin”
},
“autoload”: {
“psr-0”: {
“Crowd\\Store”: “src”
}
}
}
[/ecko_code_highlight]
Run composer install
$ composer install
You will get something like this:
Loading composer repositories with package information
Installing dependencies (including require-dev)
- Installing doctrine/instantiator (1.0.5)
Loading from cache
- Installing symfony/yaml (v2.7.2)
Loading from cache
- Installing symfony/process (v2.7.2)
Loading from cache
- Installing symfony/finder (v2.7.2)
Loading from cache
- Installing symfony/event-dispatcher (v2.7.2)
Loading from cache
- Installing symfony/console (v2.7.2)
Loading from cache
- Installing sebastian/recursion-context (1.0.0)
Loading from cache
- Installing sebastian/exporter (1.2.0)
Loading from cache
- Installing phpspec/php-diff (v1.0.2)
Loading from cache
- Installing sebastian/diff (1.3.0)
Loading from cache
- Installing sebastian/comparator (1.1.1)
Loading from cache
- Installing phpdocumentor/reflection-docblock (2.0.4)
Loading from cache
- Installing phpspec/prophecy (v1.4.1)
Loading from cache
- Installing phpspec/phpspec (2.2.1)
Loading from cache
symfony/event-dispatcher suggests installing symfony/dependency-injection ()
symfony/event-dispatcher suggests installing symfony/http-kernel ()
symfony/console suggests installing psr/log (For using the console logger)
phpdocumentor/reflection-docblock suggests installing dflydev/markdown (~1.0)
phpdocumentor/reflection-docblock suggests installing erusev/parsedown (~1.0)
phpspec/phpspec suggests installing phpspec/nyan-formatters (~1.0 – Adds Nyan formatters)
PHPSpec run command
Now that we have bin/ and vendor/ directory in our project, let’s go with this:
$ bin/phpsepc run
And you will see:
0 specs
0 examples
0ms
Play with PHPSpec
$ bin/phpspec describe Crowd/Store/Product
Will return this message:
Specification for Crowd\Store\Product created in [rootproject]/spec/Crowd/Store/ProductSpec.php
In your folder project now you will see
The content of the ProductSpec.php created file looks like this:
[ecko_code_highlight language=”php”] <?phpnamespace spec\Crowd\Store;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ProductSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType(‘Crowd\Store\Product’);
}
}
[/ecko_code_highlight]
On terminal type
$ bin/phpspec run
And now you will see this:
Type YES and you will get the next message:
And the next file structure in your project
Inside Product.php you will see
[ecko_code_highlight language=”php”]
<?php
namespace Crowd\Store;
class Product
{
}
[/ecko_code_highlight]
Now inside [rootproject]/spec/Crowd/Store/ProductSpec.php file, write the next functions
[ecko_code_highlight language=”php”]
function it_should_have_a_name()
{
$this->getName()->shouldReturn(‘Testing Spec’);
}
function it_should_have_sku()
{
$this->getSku()->shouldReturn(‘12345’);
}
[/ecko_code_highlight]
The complete files looks like:
[ecko_code_highlight language=”php”]
<?php
namespace spec\Crowd\Store;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ProductSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType(‘Crowd\Store\Product’);
}
function it_should_have_a_name()
{
$this->getName()->shouldReturn(‘Testing Spec’);
}
function it_should_have_sku()
{
$this->getSku()->shouldReturn(‘12345’);
}
}
[/ecko_code_highlight]
What are we doing here? Well, we are defining two more test functions. One to check if a function called getName() returns a string with value “Testing Spec” and the other to check if a function called getSku() returns a string with value “12345”.
On terminal lets do:
$ bin/phpspec run
It will display:
Press Y + return key:
Press Y + return key again:
What does this mean? First of all, PHPSpec checks if getName() and getSku() functions exists in the Product class. If it does not find them, it asks us if we want to create them. Once created, PHPSpec will try to run the tests, but they will not pass.
The Product.php file under [rootproject]/src/Crowd/Store/ changed its content and now looks like:
[ecko_code_highlight language=”php”]
<?php
namespace Crowd\Store;
class Product
{
public function getName()
{
// TODO: write logic here
}
public function getSku()
{
// TODO: write logic here
}
}
[/ecko_code_highlight]
That’s the reason our tests are not passing: the functions exist, but they do nothing. Lets work with them and type the following in Product.php
[ecko_code_highlight language=”php”]
<?php
namespace Crowd\Store;
class Product
{
protected $_name;
protected $_sku;
public function __construct($name = ”, $sku = ”)
{
$this->_name = $name;
$this->_sku = $sku;
}
public function getName()
{
return $this->_name;
}
public function getSku()
{
return $this->_sku;
}
}
[/ecko_code_highlight]
Run the specs again:
$ bin/phpspec run
And… oh!, they don’t pass again. Why?
This happened because phpspec is running without any init data. To do that, let’s type the following inside ProductSpec class:
[ecko_code_highlight language=”php”]
function let()
{
$name = “Testing Spec”;
$sku = “12345”;
$this->beConstructedWith($name, $sku);
}
[/ecko_code_highlight]
The let() method is used to pass data into the constructor each time the parser gets created using the beConstructedWith() method
Now on the console, type once again
$ bin/phpspec run
And we did it, friends!