---
title: "Project testing"
manual: "TYPO3 Explained"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3coreapi:testing-projects@main"
source: "Testing/ProjectTesting.rst"
modified: "2026-09-16T13:05:25+00:00"
---

# Project testing

-   [Differences between project and extension testing](https://docs.typo3.org/permalink/t3coreapi:differences-between-project-and-extension-testing@main)
-   [Project structure](https://docs.typo3.org/permalink/t3coreapi:project-structure@main)
-   [Install testing dependencies](https://docs.typo3.org/permalink/t3coreapi:install-testing-dependencies@main)
-   [Test configuration on project level](https://docs.typo3.org/permalink/t3coreapi:test-configuration-on-project-level@main)
-   [Running the tests locally](https://docs.typo3.org/permalink/t3coreapi:running-the-tests-locally@main)
-   [Organizing and storing the commands](https://docs.typo3.org/permalink/t3coreapi:organizing-and-storing-the-commands@main)

## 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](https://github.com/sbuerk/tf-basics-project)
here. If you are using another structure, you have to adjust some scripts.

-   [TYPO3 installation with Composer](https://docs.typo3.org/m/typo3/tutorial-getting-started/main/en-us/Installation/Install.html#install) and default paths
-   [DDEV](https://docs.typo3.org/m/typo3/tutorial-getting-started/main/en-us/Installation/Install.html#installation-ddev-tutorial) is used for local development
-   Local extensions and the site package are situated in `packages`

-   `.ddev`
-   `config`
-   `packages`
-   `composer.json`
-   `composer.lock`

The `composer.json` looks like this:

**Example project composer.json before testing**

```json
{
    "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": "^14.3",
        "typo3/cms-[other_dependencies]": "^14.3"
    },
    "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
        }
    }
}

```

## Install testing dependencies

As a bare minimum it is suggested to use

-   One coding style fixer for PHP, for example [`friendsofphp/php-cs-fixer`](https://packagist.org/packages/friendsofphp/php-cs-fixer)
-   One static code analyzer for PHP, for example [`phpstan/phpstan`](https://packagist.org/packages/phpstan/phpstan)

Depending on the complexity of your project you might need:

-   [`phpunit/phpunit`](https://packagist.org/packages/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](https://docs.typo3.org/permalink/t3coreapi:testing-writing-acceptance@main)

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****

```bash
composer install --no-dev
```

For TYPO3 project you can use the package [`typo3/coding-standards`](https://packagist.org/packages/typo3/coding-standards)
which already requires [`friendsofphp/php-cs-fixer`](https://packagist.org/packages/friendsofphp/php-cs-fixer) and a set of
useful configuration and rules.

**Require development dependencies**

```bash
composer req --dev typo3/coding-standards
```

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

**Require development dependencies**

```bash
composer req --dev typo3/coding-standards typo3/testing-framework
```

## 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`](https://packagist.org/packages/typo3/coding-standards) comes with a predefined configuration for
[`friendsofphp/php-cs-fixer`](https://packagist.org/packages/friendsofphp/php-cs-fixer). You can override rules as needed in
your own configuration:

**Build/php-cs-fixer/.php-cs-fixer.dist.php**

```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;

```

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**

```plaintext
includes:
  - phpstan-baseline.neon
parameters:
  level: 5

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

  tmpDir: .cache/phpstan/

  excludePaths:
    - '**/node_modules/*'

```

It also makes sense to exclude any `node_modules` directory.

### Unit and functional test configuration

See the chapters [Unit testing](https://docs.typo3.org/permalink/t3coreapi:testing-writing-unit@main) and
[Functional testing](https://docs.typo3.org/permalink/t3coreapi:testing-writing-functional@main).

## 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:

```bash
vendor/bin/php-cs-fixer fix --config=Build/php-cs-fixer/.php-cs-fixer.dist.php
```

### Run PHPStan

```bash
vendor/bin/phpstan --configuration=Build/phpstan/phpstan.neon
```

Regenerate the baseline:

```bash
vendor/bin/phpstan \
    --configuration=Build/phpstan/phpstan.neon \
    --generate-baseline=Build/phpstan/phpstan-baseline.neon
```

### Run unit tests

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

```bash
vendor/bin/phpunit \
    -c Build/phpunit/UnitTests.xml
```

### Run functional tests using sqlite and DDEV

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

### Run functional tests using mysqli and DDEV

**typo3_root$**

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

## Organizing and storing the commands

There are different solutions to store and execute these command.
For details see [Test runners: organize and execute tests](https://docs.typo3.org/permalink/t3coreapi:testing-organization@main).
