---
title: "Project testing"
manual: "TYPO3 Explained"
version: "12.4"
permalink: "https://docs.typo3.org/permalink/t3coreapi:testing-projects@12.4"
source: "Testing/ProjectTesting.rst"
rendered: "2026-10-21T15:29:37+00:00"
---

> [!WARNING]
> **Attention**
>
> TYPO3 v12 has reached end-of-life as of April 30th 2026 and
> is no longer being maintained. Use the version switcher on the top
> left of this page to select documentation for a supported version of TYPO3.
>
> Need more time before upgrading?
> You can purchase Extended Long Term Support (ELTS) for TYPO3 v12 here:
> [TYPO3 ELTS](https://typo3.com/services/extended-support-elts).

# Project testing {#testing-projects}

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

## Differences between project and extension testing {#testing-projects-differences}

**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 {#testing-projects-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/12.4/en-us/Installation/Install.html#install) and default paths
-   [DDEV](https://docs.typo3.org/m/typo3/tutorial-getting-started/12.4/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": "^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
        }
    }
}

```

## Install testing dependencies {#testing-projects-installation}

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@12.4)

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 bundles [`friendsofphp/php-cs-fixer`](https://packagist.org/packages/friendsofphp/php-cs-fixer), [`phpstan/phpstan`](https://packagist.org/packages/phpstan/phpstan),
[`phpunit/phpunit`](https://packagist.org/packages/phpunit/phpunit) and some other helpful tools and comes with useful
configurations for these.

**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 {#testing-projects-configuration}

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 {#testing-projects-configuration-cs}

[`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 {#testing-projects-configuration-phpstan}

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/*'
    - '**/ext_emconf.php'

```

It also makes sense to exclude the [`ext_emconf.php`](../ExtensionArchitecture/FileStructure/ExtEmconf.md#file-extension-ext-emconf-php) and any
`node_modules` directory.

### Unit and Functional test configuration {#testing-projects-configuration-phpunit}

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

## Running the tests locally {#testing-projects-execution}

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

### Run the php-cs-fixer {#testing-projects-execution-cs}

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 {#testing-projects-execution-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 {#testing-projects-execution-phpunit}

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 {#testing-projects-execution-functional-sqlite}

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

### Run Functional tests using mysqli and DDEV {#testing-projects-execution-functional-mysqli}

```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 {#testing-projects-organization}

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@12.4).
