Skip to content

Setting up PHPQA for Symfony Project

First, Install PHPQA

composer require edmondscommerce/phpqa --dev

You will get options to run recipes, along the lines of:

Writing lock file
Generating autoload files
Symfony operations: 2 recipes (879dfdbdec43c895e4cad33b1dfef4e5)
  -  WARNING  squizlabs/php_codesniffer (>=3.0): From github.com/symfony/recipes-contrib:master
    The recipe for this package comes from the "contrib" repository, which is open to community contributions.
    Review the recipe at https://github.com/symfony/recipes-contrib/tree/master/squizlabs/php_codesniffer/3.0

    Do you want to execute this recipe?
    [y] Yes
    [n] No
    [a] Yes for all packages, only for the current installation session
    [p] Yes permanently, never ask again for this project
    (defaults to n): 

You should say no to the codesniffer recipe (default, just hit return)

You will also get something about PHPUnit

 Adding phpunit/phpunit as a dependency is discouraged in favor of Symfony's PHPUnit Bridge. 


  * Instead:
    1. Remove it now: composer remove --dev phpunit/phpunit
    2. Use Symfony's bridge: composer require --dev phpunit

Again you should ignore this, it is all handled by PHPQA

Remove Cruft That is Added After installing PHPQA

rm .php_cs.dist

PHPUnit Configs

First of all, we need to set up some PHPQA configuration for PHPUnit

We will copy the generated XML file first of all

mkdir qaConfig
mv phpunit.xml.dist qaConfig/phpunit.xml

Then we need to fix the paths, by adding ../

For example:

<?xml version="1.0" encoding="UTF-8"?>

<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->

<!-- here, twice
- once for xsd
- once for bootstrap
 //-->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="../vendor/phpunit/phpunit/phpunit.xsd"
         backupGlobals="false"
         colors="true"
         bootstrap="../config/bootstrap.php"
>
    <php>
        <ini name="error_reporting" value="-1" />
        <server name="APP_ENV" value="test" force="true" />
        <server name="SHELL_VERBOSITY" value="-1" />
    </php>

    <testsuites>
        <testsuite name="Project Test Suite">
<!-- here //-->
            <directory>../tests</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
<!-- here //-->
            <directory>../src</directory>
        </whitelist>
    </filter>
</phpunit>

We also need to add PHPQA configurations:

Basic Configs

<phpunit
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="../vendor/phpunit/phpunit/phpunit.xsd"
        cacheTokens="false"
        colors="true"
        verbose="true"
        forceCoversAnnotation="false"
        printerClass="\PHPUnit\Util\TestDox\CliTestDoxPrinter"
        timeoutForMediumTests="30"
        timeoutForSmallTests="3"
        timeoutForLargeTests="300"
        failOnRisky="true"
        failOnWarning="true"
        defaultTestSuite="Project Test Suite"
        beStrictAboutTodoAnnotatedTests="true"
        cacheResult="true"
        cacheResultFile="../var/qa/.phpunit.result.cache"
        executionOrder="depends,random"
        bootstrap="../tests/bootstrap.php"
        convertDeprecationsToExceptions="false"
>

Logging

    <logging>
        <log type="coverage-html" target="../var/qa/phpunit_coverage"/>
        <log type="coverage-text" target="php://stdout"/>
        <log type="coverage-xml" target="../var/qa/phpunit_logs/coverage-xml"/>
        <log type="junit" target="../var/qa/phpunit_logs/phpunit.junit.xml"/>
    </logging>

Kernel Class

As we are not using the App namespace, we need to change the Kernel Class

<php>
        <env name="KERNEL_CLASS" value="\ProjectName\Kernel"/>
    </php>

So the final phpunit.xml file might look something like:

<?xml version="1.0" encoding="UTF-8"?>

<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="../vendor/phpunit/phpunit/phpunit.xsd"
        cacheTokens="false"
        colors="true"
        verbose="true"
        forceCoversAnnotation="false"
        printerClass="\PHPUnit\Util\TestDox\CliTestDoxPrinter"
        timeoutForMediumTests="30"
        timeoutForSmallTests="3"
        timeoutForLargeTests="300"
        failOnRisky="true"
        failOnWarning="true"
        defaultTestSuite="Project Test Suite"
        beStrictAboutTodoAnnotatedTests="true"
        cacheResult="true"
        cacheResultFile="../var/qa/.phpunit.result.cache"
        executionOrder="depends,random"
        bootstrap="../tests/bootstrap.php"
        convertDeprecationsToExceptions="false"
>
    <php>
        <ini name="error_reporting" value="-1" />
        <server name="APP_ENV" value="test" force="true" />
        <server name="SHELL_VERBOSITY" value="-1" />
        <env name="KERNEL_CLASS" value="\ProjectName\Kernel"/>
    </php>
    <logging>
        <log type="coverage-html" target="../var/qa/phpunit_coverage"/>
        <log type="coverage-text" target="php://stdout"/>
        <log type="coverage-xml" target="../var/qa/phpunit_logs/coverage-xml"/>
        <log type="junit" target="../var/qa/phpunit_logs/phpunit.junit.xml"/>
    </logging>
    <testsuites>
        <testsuite name="Project Test Suite">
            <directory>../tests</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>../src</directory>
        </whitelist>
    </filter>
</phpunit>

Tests Bootstrap File

#tests/bootstrap.php
<?php 

declare(strict_types=1);

# bring in standard symfony bootstrap
require __DIR__ . '/../config/bootstrap.php';

# truncate test logs
file_put_contents(__DIR__ . '/../var/log/test.log', 'Test started at ' . date('H:i:s') . "\n");
ln -s qaConfig/phpunit.xml

This allows us to run ./bin/phpunit from the project root

15:29 $ ./bin/phpunit
PHPUnit 8.2.5 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.2.12 with Xdebug 2.6.1
Configuration: /var/www/vhosts/project-name/qaConfig/phpunit.xml
Random seed:   1574263804


Time: 39 ms, Memory: 4.00 MB

No tests executed!

Generating code coverage report in HTML format ... done [20 ms]


Code Coverage Report:   
  2019-11-20 15:30:03   

 Summary:               
  Classes:  0.00% (0/1) 
  Methods:  0.00% (0/4) 
  Lines:    0.00% (0/27)

Configure Infection

We need to tell infection to use our configs, so we need to set up a config file for it in our qaConfig folder

qaConfig/infection.json

{
  "timeout": 10,
  "source": {
    "directories": [
      "src"
    ],
    "excludes": [
      "Kernel.php"
    ]
  },
  "note:": [
    "yes paths are handled inconsistently",
    "the logs paths are from the project root",
    "the tmp path is from the config file location"
  ],
  "logs": {
    "text": "var/qa/infection/log.txt",
    "summary": "var/qa/infection/summary-log.txt",
    "debug": "var/qa/infection/debug-log.txt"
  },
  "phpUnit": {
    "configDir": "../qaConfig"
  },
  "tmpDir": "../var/qa/infection/tmp"
}

Fixing Composer Require Issues

PHPQA Checks for explicit requires of dependencies that are used in project code

As a minimum, we need to add the following:

composer require symfony/http-kernel  symfony/dependency-injection  symfony/config  symfony/routing 

Create a README File

We need to have a project README.md file

Create one and document the project in there