Project testing

Differences between project and extension testing

Projects usually needs to support only one PHP version, Database vendor and version and TYPO3 core version

Version raises for upgrades are usually prepared on a branch and changed instead of parallel execution.

Project may have different places for tests

  • local path extension tests packages/*/Tests/*
  • global (root) tests Tests/*

The Core mono repository is basically a project setup, having local path extensions in typo3/sysexts/* instead of the more known and lived packages/* project folder structure.

Project structure

We assume a project structure similar to tf-basics-project here. If you are using another structure, you have to adjust some scripts.

  • .ddev
  • config
  • packages
  • composer.json
  • composer.lock

The composer.json looks like this:

Example project composer.json before testing
{
    "name": "sbuerk/tf-basics-project",
    "description": "TYPO3 Demo Project to demonstrate basic testing integration",
    "license": "GPL-2.0-or-later",
    "type": "project",
    "require": {
        "internal/custom-command": "@dev",
        "internal/custom-middleware": "@dev",
        "typo3/cms-core": "^12.4",
        "typo3/cms-[other_dependencies]": "^12.4"
    },
    "repositories": {
        "extensions": {
            "type": "path",
            "url": "packages/*"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "SBUERK\\TfBasicsProject\\Tests\\": "Tests/"
        }
    },
    "config": {
        "allow-plugins": {
            "typo3/class-alias-loader": true,
            "typo3/cms-composer-installers": true
        }
    }
}
Copied!

Install testing dependencies

As a bare minimum it is suggested to use

Depending on the complexity of your project you might need:

  • phpunit/phpunit , if there is any PHP code of a complexity that should be tested.
  • Testing of scss, TypeScript or JavaScript (not covered here)
  • Linting of YAML, XML, TypoScript (not covered here)
  • Writing acceptance tests

You can install all these tools as development dependencies. They will then not be installed on your production system when Composer is executed with option --no-dev during deployment:

Composer installation during deployment
composer install --no-dev
Copied!

For TYPO3 project you can use the package typo3/coding-standards which bundles friendsofphp/php-cs-fixer , phpstan/phpstan , phpunit/phpunit and some other helpful tools and comes with useful configurations for these.

Require development dependencies
composer req --dev typo3/coding-standards
Copied!

If you want to do Unit or Functional tests on project level you also need the TYPO3 testing framework:

Require development dependencies
composer req --dev typo3/coding-standards typo3/testing-framework
Copied!

Test configuration on project level

We suggest to keep all project level test configuration in a common place that can be excluded from deployment. The Core uses a folder called Build with one folder per test-type and we will follow that scheme here. If you put the configuration in other directories, adjust your configuration files accordingly.

Code style tests and fixing

typo3/coding-standards comes with a predefined configuration for friendsofphp/php-cs-fixer . You can override rules as needed in your own configuration:

Build/php-cs-fixer/.php-cs-fixer.dist.php
<?php

$config = \TYPO3\CodingStandards\CsFixerConfig::create();
$baseDir = __DIR__ . '/../../';
$config->getFinder()
    ->in($baseDir . 'config')
    ->in($baseDir . 'packages/*/Classes')
    ->in($baseDir . 'packages/*/Configuration')
    ->in($baseDir . 'packages/*/Tests')
    ->in($baseDir . 'packages/*.php')
    ->in($baseDir . 'Tests')
    ->exclude('Fixtures')
;
return $config;
Copied!

It is recommended to also copy the .editorconfig from the testing framework into your main directory so that your IDE applies the same formatting as the php-cs-fixer.

PHPstan - Static PHP analysis

When configuring PHPstan the various places in which PHP files can be found should be taken into consideration:

Build/phpstan/phpstan.neon
includes:
  - phpstan-baseline.neon
parameters:
  level: 5

  paths:
    - ../../config
    - ../../packages
    - ../../Tests

  tmpDir: .cache/phpstan/

  excludePaths:
    - '**/node_modules/*'
    - '**/ext_emconf.php'
Copied!

It also makes sense to exclude the ext_emconf.php and any node_modules directory.

Unit and Functional test configuration

See the chapters Unit testing and Functional testing.

Running the tests locally

The tests can be run via PHP on your local machine or with DDEV.

Run the php-cs-fixer

To run the php-cs-fixer you need to configure the path to the configuration file:

vendor/bin/php-cs-fixer fix --config=Build/php-cs-fixer/.php-cs-fixer.dist.php
Copied!

Run PHPstan

vendor/bin/phpstan --configuration=Build/phpstan/phpstan.neon
Copied!

Regenerate the baseline:

vendor/bin/phpstan \
    --configuration=Build/phpstan/phpstan.neon \
    --generate-baseline=Build/phpstan/phpstan-baseline.neon
Copied!

Run Unit tests

As Unit tests need no database or other dependencies you can run them directly on your host system or DDEV:

vendor/bin/phpunit \
    -c Build/phpunit/UnitTests.xml
Copied!

Run Functional tests using sqlite and DDEV

ddev exec \
    typo3DatabaseDriver=pdo_sqlite \
    php vendor/bin/phpunit -c Build/phpunit/FunctionalTests.xml
Copied!

Run Functional tests using mysqli and DDEV

ddev exec \
    typo3DatabaseDriver='mysqli' \
    typo3DatabaseHost='db' \
    typo3DatabasePort=3306 \
    typo3DatabaseUsername='root' \
    typo3DatabasePassword='root' \
    typo3DatabaseName='func' \
    php vendor/bin/phpunit -c Build/phpunit/FunctionalTests.xml
Copied!

Organizing and storing the commands

There are different solutions to store and execute these command. For details see Test Runners: Organize and execute tests.