Porting your PHPUnit legacy test suite to PhpSpec Adventures: Part VI

Previous episodes:

Sharing some experiences while moving a phpunit test suite over to PhpSpec.

– The treatment of abstract classes, say in PhpSpec I find hard to describe an abstract class because it cannot be properly instantiated. There was one class Email.php in the namshi/notificator library that I had to skip. The class was abstract, however the implementation of the class which was a class Emailvision.php which extended this class was describable so I think it was sufficient to keep only that spec and not worrying about describing abstract classes.

– There were several classes that had `shouldHandle`, mainly all the handler implementations. This caused a bug in PhpSpec that prevented me from utilizing the methods to spec the object. PhpSpec thought I was trying to call a matcher directly on the object and therefore there were no matchers. I tried several workarounds however my friend Leszek @l3l0 suggested me to use `getWrappedObject` method. So I did and since I did not want to use phpunit asserts just for this temporary situation I just created if statements around the actual results of the invocation of these methods.

    // ...
    function it_should_handle_emailvision_notifications_only()
        $emailvisionNotification = new EmailvisionNotification('a', 'b', []);
        $otherNotification = new EmailNotification('a', []);
        if (!$this->getWrappedObject()->shouldHandle($emailvisionNotification)) {
            throw new \Exception('fails');
        if ($this->getWrappedObject()->shouldHandle($otherNotification)) {
            throw new \Exception('fails');

– On test suite migration the best feeling is that after it is finished every other new feature would become pluggable and that we would have a green state from where to start. And that we would use BDD all the way and have 100% coverage by methodology. In the way of exporting the suite I found some code, mainly getters and setters, which were not very clear why they were created since there was no need for the use cases described in the tests. In BDD we don’t write code that is not described so in these cases it is preferable to remove the unused getters and setters in each case and rely on utilization within the class on the direct properties.

– The usage of the gruntjs trick for running the tests continuously is an amazing help. There is a problem however when you describe a class or an interface which is not created and the test suite gets run but because grunt runs without interaction there is no way to type yes or no back to the console so one has to kill the watcher, run manually to prompt for generation of the class, and then run the grunt watcher again. Because it was an already written library the instances of this issue were minimum; however, I noticed it could have been worst should the number of creations of new classes were high.

– PhpSpec forces you to correct some problems in the library, such as avoiding breaking Demeter’s law, encourages encapsulation and injecting the right collaborators, improves the readability of tests via its snake case definition of spec methods, focuses on use cases rather than on testing, avoids boilerplate code, makes sure it is a unitary focus on the SUS, and overall helps defining and exploring the architecture.

– Using Phpunit with Prophecy library is better than just using Phpunit, however, using PhpSpec which has already integrated Prophecy is far better with less boilerplate code. After transferring a test suite to a spec suite, your brain starts to change, you start thinking on use cases rather than details on the implementation, and your mind gets ready to architect rather than to monkey code.

Please share your ideas on the comments below.
I will be looking at writing a bundle for the library using PhpSpec from the beginning.

If you would like to say thanks by supporting me please get the Lean Book on Symofony2 Ecommerce thanks!

undeservedly thankful, your friend @cordoval

Leave a Reply

Your email address will not be published. Required fields are marked *