Using Drone to automate PHPUnit - more things I've learned

A few things I’ve learnt while automating this.

I should note that, because of the issues with the standard Docker PHPUnit image, I’m still using the yourpropertyexpert one. (Yes, I’ve submitted it back to the official PHPUnit project.)

Firstly, PHPUnit requires some autoloading of classes. In a drone context (where PHP needs to be tested standalone rather in a composer-heavy environment), it’s worth creating a ./autoload-drone.php file to put in your tests directory, and have the autoloading configured there. Then you run the following drone pipeline stage:

- name: Unit tests 
  image: yourpropertyexpert/myphpunit:first
  commands:
  - cd /drone/src/<path to your custom classes>/tests
  - /var/www/html/vendor/bin/phpunit --bootstrap ./autoload-drone.php .

Secondly, and this was a bit more fiddly, some PHP files need to be able to the file directive to open (server local) files. Getting this to work in normal PHP tends to involve use of the superglobal $_SERVER[‘DOCUMENT_ROOT’];

PHP running in the drone container doesn’t have the same context, so you need to do two things…

a) set the location by which drone will think of the root as an environment variable in the drone pipeline
b) In the unit test itself, over-write the superglobal.

So your .drone.yml looks like:

- name: Unit tests 
  image: yourpropertyexpert/myphpunit:first
  commands:
  - cd /drone/src/<path to your custom classes>/tests
  - export DRONE_DOC_ROOT=/drone/src/api/
  - /var/www/html/vendor/bin/phpunit --bootstrap ./autoload-drone.php .

And your Unit Test (for a class called Generator) looks like:

class RenderTest extends TestCase
{
    private $generator;
    protected function setUp(): void
    {
        $this->generator=new Generator();
    }

    public function testGeneratorObjectExists()
    {
        $this->assertIsObject($this->generator);
    }

    public function testGeneratorMethodsReturnTypes()
    {
        // The generator class needs to open a file of
        // words, which is relative to DOCUMENT_ROOT
        // For drone purposes, we need to spoof that
        if (getenv('DRONE_DOC_ROOT')) {
            $_SERVER['DOCUMENT_ROOT']=getenv('DRONE_DOC_ROOT');
        }
        $this->assertIsString($this->generator->Method1());
        $this->assertIsString($this->generator->Method2());
    }
}