Quantcast
Channel: Craft It Online!
Viewing all articles
Browse latest Browse all 92

PHPSpecking From Bus Tour to Huaraz: Part IV

$
0
0

I a on a bus PHPSpecking, today I was contributing to namshi/notificator repository and attempted to replace a phpunit test to learn Prophecy library tied to PHPSpec. Here I will show first the result and then the PHPUnit old file so you can compare. I learned lots on the way.

<?php
 
namespace spec\Namshi\Notificator;
 
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
 
class ManagerSpec extends ObjectBehavior
{
    function it_is_initializable()
    {
        $this->shouldHaveType('Namshi\Notificator\Manager');
    }
 
    function it_comes_with_no_handlers_by_default()
    {
        $this->getHandlers()->shouldHaveCount(0);
    }
 
    /**
     * @param Namshi\Notificator\Notification\Handler\HandlerInterface $handler
     */
    function it_can_hold_several_handlers($handler)
    {
        $this->addHandler($handler);
        $this->addHandler($handler);
        $this->getHandlers()->shouldHaveCount(2);
    }
 
    /**
     * @param \Namshi\Notificator\Notification\Handler\HandlerInterface $handler
     * @param \Namshi\Notificator\NotificationInterface $notification
     */
    function it_can_stop_propagation_of_notifications($handler, $notification)
    {
        foreach (range(1,6) as $i) { $this->addHandler($handler); };
        $this->getHandlers()->shouldHaveCount(6);
 
        $handler->shouldHandle(Argument::any())->shouldBeCalled()->willReturn(true);
        $handler->handle(Argument::any())->shouldBeCalledTimes(1)->willReturn(false);
 
        $this->trigger($notification);
    }
}

And here is the old class:

<?php
 
namespace Namshi\Notificator\Test;
 
use PHPUnit_Framework_TestCase;
use Namshi\Notificator\Manager;
use Namshi\Notificator\Notification\Handler\HandlerInterface;
use Namshi\Notificator\NotificationInterface;
 
 
class ManagerTest extends PHPUnit_Framework_TestCase
{
    public function setup()
    {
        $this->manager = new Manager();
    }
 
    public function testTheManagerDoesntHaveHandlersByDefault()
    {
        $this->assertCount(0, $this->manager->getHandlers());
    }
 
    public function testTheManagerCanHaveMultipleHandlers()
    {
        $this->manager->addHandler(new StubHandler());
        $this->manager->addHandler(new StubHandler());
 
        $this->assertCount(2, $this->manager->getHandlers());
    }
 
    public function testTheManagerCanTriggerNotificationsToAllHandlers()
    {
        $this->manager->addHandler(new StubHandler());
        $this->manager->addHandler(new StubHandler());
        $notification = new StubNotification();
        $this->manager->trigger($notification);
 
        $this->assertEquals(2, $notification->count);
    }
 
    public function testTheManagerCanStopPropagationOfNotifications()
    {
        $this->manager->addHandler(new StubHandler(true));
        $this->manager->addHandler(new StubHandler());
        $this->manager->addHandler(new StubHandler());
        $this->manager->addHandler(new StubHandler());
        $this->manager->addHandler(new StubHandler());
        $this->manager->addHandler(new StubHandler());
        $notification = new StubNotification();
        $this->manager->trigger($notification);
 
        $this->assertCount(6, $this->manager->getHandlers());
        $this->assertEquals(1, $notification->count);
    }
}
 
class StubHandler implements HandlerInterface
{
    public function __construct($stopPropagation = false)
    {
        $this->stopPropagation = $stopPropagation;
    }
 
    public function shouldHandle(NotificationInterface $notification)
    {
        return true;
    }
 
    public function handle(NotificationInterface $notification)
    {
        $notification->count++;
 
        if ($this->stopPropagation) {
            return false;
        }
    }
}
 
class StubNotification implements NotificationInterface
{
    public $count = 0;
 
    public function getParameters()
    {
 
    }
 
    public function setParameters(array $parameters)
    {
 
    }
}

Things to notice:

- We don’t have to do a mental effort on writing the method names for testing and just write describing true features of our object
- You want to save your mental energy to describe behavior not to read difficult camel case names on tests. I mean we are cool with camel case on the class but not need for them when describing specific features of the behavior.
- Looking underneath those `should`s, `will`s and `shouldHave`s is the core mind of what Prophecy is. It is similar to reality where it has to do with hope, fulfillment, and scrutinizing fulfillment to convey one step at a time a widening panorama of the salvation plan and the divine person self revealing. In our case is design, we prophesy by describing using these tools and the design force implements these expectations that get fulfilled in its time. The descriptions remain to validate the body of truth about the design. These methods are really just built-in shortcuts to mock and stub and to set forth for us object manipulations with which we can take onto this task.
- If you compare both codes, you will see that the shortcuts make PHPSpec superior and cleaner, more easy to read than its predecessors.
- One really neat thing that PHPSpec would prompt you to, is the fact that it will fire up a special exception if part of the behavior of your class gets called but it is not specified or described. This thing is really useful because it keeps you accountable and true with the context of how your collaborators are used in the story you are telling.
- As a result you will also observe that we need nothing extra besides our testing class. We don’t need to pollute the file we are in with adhoc classes created just for stubbing or mocking. PHPSpec plays hand in hand with Prophecy to help you do this without being too verbose. You will focus on behavior not on boiler plat code with this tool.
- The other thing not to miss is the concept of arguments. When you are specking with PHPSpec arguments are not plain arguments but objects that will help you intelligently address internal needs and expectations. This has to do with addressing specific behavior for calls of the methods described with specific signatures and arguments. Prophecy has a built-in voting mechanism in which your matching has scores and the best signature fit case will win. Smart move from @everzet and @_md.
- Again from 92 lines to 44 lines. I am not sure about you but I see a winner.

Man i am seing beautiful mountains here. I will try to post some images on a later blog post. Going in zigzag right now through the valleys high altitudes and amazing places of Peru in a bus that powers this asus g73 gaming grade :) (retina is on repair).The only thing that is making me sick is the smell or artificial cleaning smell on the bus. That combined with the roller coaster in the few hours hopefully will not be enough to make me throw up. I hope you guys enjoy learning with me so far. I am very thankful for all this undeserved specking tour.


Viewing all articles
Browse latest Browse all 92

Trending Articles