Follow Up: Keeping Your Module Structure Intact When Running Front-end Tests in PyroCMS

UPDATE: PyroCMS now scaffolds tests when using make:addon by default, and this issue has been resolved. Huzzah!

This is a follow up article to the my previous article, Setting Up Module-Based Tests for PyroCMS. One thing that I discovered was that the creation of front-end tests on a per-module basis in PyroCMS would lead to the generation of an app/ folder which had theme assets contained within:

test_run
Test suite run that generates additional folders.

This leads to the following directory structure being added:

It seems that PyroCMS’ asset loader uses relative paths. I’ve talked to the amazing Ryan Thompson (creator of PyroCMS) about the issue, but in the meantime, we can make a simple work around to correct this issue.

Firstly, we’ll create a PHPUnit listener in our tests folder, similar to how we created our module’s TestCase in the last article. As we want to only set certain methods on the Listener, we will extend PHPUnit_Framework_BaseTestListener, rather than implementing  PHPUnit_Framework_TestListener(which requires all methods). Within that TestListener, we’ll define the endTestSuite function, which takes the currently ending TestSuite as an argument:

<?php
use Symfony\Component\Console\Output\ConsoleOutput;
use Illuminate\Filesystem\Filesystem;

class ProfilesModuleTestListener extends PHPUnit_Framework_BaseTestListener
{
   public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
       $appAssetDir = __DIR__ . '/../app';
       $fs = new Filesystem;
       if ($fs->exists($appAssetDir)) {
           app(ConsoleOutput::class)->writeln('<info>App assets were generated by theme during ' . $suite->getName() . ' at ' . $appAssetDir . '. Removing...</info>');
           $fs->deleteDirectory($appAssetDir);
       }
    }
}
?>

We’ve got a few things going on here. Firstly, We’re going to use the excellent ConsoleOutput class from Symfony that is utilised by Laravel, as well as the Filesystem class. We’ll use this as it’s got simple methods for recursively deleting directories.

In our method, we’re looking for the generated /app class within our module folder, as we know that’s what is being created during test cases. If we find an existence of the directory, we simply output console output informing the test runner about it, and then recursively remove the directory with deleteDirectory.

The final step is to let PHPUnit know about our Listener by inserting a <listeners>key into our phpunit.xml like so:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="../../../../bootstrap/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Application Test Suite">
            <directory suffix="Test.php">./tests</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./src</directory>
        </whitelist>
    </filter>
    <listeners>
      <listener class="ProfilesModuleTestListener" file="./tests/ProfilesModuleTestListener.php">
      </listener>
    </listeners>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
    </php>
</phpunit>

Now we can run our test suite, and voila!

phpunittestlistener

I’m currently working on a make: command for PyroCMS that will allow you to quickly scaffold a basic test system for addons, which will hopefully make it’s way into the PyroCMS core at some point. Until then, these two articles should help you setup a reusable test setup for both unit and feature tests in your addons in PyroCMS.

If you have any questions or suggestions, please don’t hesitate to contact me.

Craig Berry Written by: