To ensure your plugin's functionality, it's highly recommended to automatically test your source code. For this purpose, you can easily setup a PHPUnit testing environment for plugins.
This quick HowTo requires you to have a proper working plugin first.
Basically, the following is just a suggestion on how to setup PHPUnit with your plugin. This is by no means a hard requirement, feel free to create your own testing suite.
PHPUnit is configured using a phpunit.xml.dist
file.
Read more about the possible configurations of the phpunit.xml.dist
file here.
Here's what your plugin's phpunit.xml.dist
file could look like:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/7.1/phpunit.xsd"
bootstrap="../../../vendor/shopware/platform/src/Core/TestBootstrap.php"
cacheResult="false">
<php>
<ini name="error_reporting" value="-1"/>
<server name="KERNEL_CLASS" value="Shopware\Development\Kernel"/>
<env name="APP_ENV" value="test"/>
<env name="APP_DEBUG" value="1"/>
<env name="APP_SECRET" value="s$cretf0rt3st"/>
<env name="SHELL_VERBOSITY" value="-1"/>
</php>
<testsuites>
<testsuite name="Example Testsuite">
<directory>tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">./</directory>
</whitelist>
</filter>
</phpunit>
You're also free to add and remove configurations, so the testsuite perfectly fits your needs.
Important to note is the bootstrap
configuration in the phpunit
element.
In this example, you're required to put your tests into the tests
directory.
Here's an example test, which simply tries to instantiate every .php
class, to see if any used core classes
went missing:
<?php declare(strict_types=1);
namespace Swag\PluginTestingTests;
use Shopware\Core\Framework\Test\TestCaseBase\IntegrationTestBehaviour;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Finder\Finder;
class UsedClassesAvailableTest extends TestCase
{
use IntegrationTestBehaviour;
public function testClassesAreInstantiable(): void
{
$namespace = str_replace('\Test', '', __NAMESPACE__);
foreach ($this->getPluginClasses() as $class) {
$classRelativePath = str_replace(['.php', '/'], ['', '\\'], $class->getRelativePathname());
$this->getMockBuilder($namespace . '\\' . $classRelativePath)
->disableOriginalConstructor()
->getMock();
}
// Nothing broke so far, classes seem to be instantiable
$this->assertTrue(true);
}
private function getPluginClasses(): Finder
{
$finder = new Finder();
$finder->in(realpath(__DIR__ . '/../'));
$finder->exclude('Test');
return $finder->files()->name('*.php');
}
}
Make sure to have a look at the IntegrationTestBehaviour
trait, which comes in with some handy features,
such as automatically setting up a database transaction or clearing the cache before starting your tests.
For easier usage, you could create a batch file called phpunit.sh
into a bin
directory of your plugin.
Its only purpose then would be executing the PHPUnit
testsuite.
Make sure the path in the following file actually fits.
#!/usr/bin/env bash
./../../../vendor/bin/phpunit
Now you can simply run bin/phpunit.sh
inside your plugin root directory to execute your plugin's tests.
Also make sure to have a look at the Symfony PHPUnit documentation.
There's a GitHub repository available, containing this example source. Check it out here.
If you use the production template (which is also used by the zipped download version), you have to change a few things.
First the path to the bootstrap file is different, because there's no shopware/platform
, but shopware/core
.
So we have to change vendor/shopware/platform/src/Core/TestBootstrap.php
to vendor/shopware/core/TestBootstrap.php
.
We also need to change the KERNEL_CLASS
from Shopware\Development\Kernel
to Shopware\Production\Kernel
.
An example config:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/7.1/phpunit.xsd"
bootstrap="../../../vendor/shopware/core/TestBootstrap.php"
cacheResult="false">
<php>
<ini name="error_reporting" value="-1"/>
<server name="KERNEL_CLASS" value="Shopware\Production\Kernel"/>
<env name="APP_ENV" value="test"/>
<env name="APP_DEBUG" value="1"/>
<env name="APP_SECRET" value="s$cretf0rt3st"/>
<env name="SHELL_VERBOSITY" value="-1"/>
</php>
<testsuites>
<testsuite name="Example Testsuite">
<directory>tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">./</directory>
</whitelist>
</filter>
</phpunit>
Additionally, you have to create a database with the name $DBNAME_test
.
For example if your database is shopware
the tests will use the shopware_test
database.
This database needs to be set up with basic data. This can accomplished by
running DATABASE_URL=$myconnectionstring_test bin/console system:install --basic-data
or
by coping a clean working database.