Testing and developing a Codeception module 01

Sharing what I learnt while writing tests for my Codeception modules.

Sorely missing tests

This tweet by Jeffrey Way got me thinking

Nobody wants to admit that lots of the best practices in PHP often boil down to “Well, you have to structure it like this to test/mock it.”

He’s right and I’m shamelessly pointing you to Laracasts. Yes it’s mainly about Laravel, yes I do 99% of my work in a WordPress environment and yes I find it the best place to learn PHP on the web beside writing PHP.
I’ve developed the wp-browser modules for Codeception out of necessity: I wanted to make testing easier in a WordPress environment.
As many “itches” I’ve run to scratch it through code as fast as possible.
The project has outgrown its first scope and application and its lack of real tests stands out like a sore thumb.

Anyone in TDDing Codeception modules?

Codeception is a testing suite that can be extended using modules; there are guides available online about Codeception module development but those will just deal with module scaffolding and introductory notes.
Since I will walk the path of TDDing, or rather refactor using tests, the modules I’ve written so far I will share some gotchas along the way.

The subject under test

However the spanning tree of dependencies and accessory classes evolves the core of the development is an extension of the Codeception\Module class.
The module needs an instance of the Codeception\Lib\ModuleContainer and a config object to work.
Looking up Codeception own tests the I was able to understand how to get hold of a working instance of a module; in the case of the EmbeddedWP class

<?php
namespace Codeception\Module;


class EmbeddedWPTest extends \Codeception\TestCase\Test
{
    /**
     * @var \UnitTester
     */
    protected $tester;

    protected function _before()
    {
    }

    protected function _after()
    {
        Test::tearDown();
    }

    public function test_can_instantiate_module()
    {
        $config = [];
        $sut = new EmbeddedWP(make_container(), $config);

        $this->assertInstanceOf('Codeception\Module\EmbeddedWP', $sut);
    }

}

the make_contaner function is just a wrapper around the stubbing of the module container (taken straight from Codeception tests)

function make_container()
{
    return \Codeception\Util\Stub::make('Codeception\Lib\ModuleContainer');
}

Injecting dependencies in the module

The module __construct method will be called under the hood by Codeception and will be passed the two required arguments; additional arguments can be used to inject dependencies into the module

public function __construct(ModuleContainer $moduleContainer, $config = null, Dependency1 $dependency1 = null, Dependency2 $dependency2 = null)
{
    parent::__construct($moduleContainer, $config);
    $this->dependency1 = $dependency1 ?: new Dependency1();
    $this->dependency2 = $dependency2 ?: new Dependency2();
}

An educated defaulting will do the rest.

Next

I will move on with the tests and will keep posting my discoveries along the way.