Testbase::dumpClassLoadingInformation() (Classes/Core/Testbase.php:767-773) is called unconditionally from Resources/Core/Build/UnitTestsBootstrap.php (and internally from setUpBasicTypo3Bootstrap() for functional tests), with no check for composer mode:
public function dumpClassLoadingInformation(): void
{
if (!ClassLoadingInformation::isClassLoadingInformationAvailable()) {
ClassLoadingInformation::dumpClassLoadingInformation();
ClassLoadingInformation::registerClassLoadingInformation();
}
}
Every other caller of this functionality in typo3/cms-core (DumpAutoloadCommand, MaintenanceController, SetupService, ClassLoadingInformationUpdater) guards it with !Environment::isComposerMode(), since dumping classic-mode autoload info is meaningless when Composer's own autoloader is authoritative. This one call site doesn't, so every phpunit run using the shipped UnitTestsBootstrap.php (or any functional test) dumps autoload_classmap.php, autoload_psr4.php, autoload_files.php, autoload_classaliasmap.php into ClassLoadingInformation::getClassLoadingInformationDirectory().
In a composer-mode project using the "new directory structure" (project root ≠ public web root), that directory resolves to <project-root>/packages/autoload/ (TYPO3\CMS\Core\Core\Environment::$extensionsBasePath = $projectPath . '/packages/ext', and ClassLoadingInformation derives its dump dir from dirname() of that path). Many TYPO3 projects — including the pattern documented in TYPO3's own Composer best-practices guide — use exactly packages/ at the project root for their own local extensions (symlinked via a composer path repository), so every test run leaves an untracked, uncommitted packages/autoload/ directory sitting next to the project's real local extensions.
GuardDumpClassLoadingInformationInComposerMode.patch
Steps to reproduce
- Set up a TYPO3 14 project in composer mode with the "new directory structure" (
extra."typo3/cms".web-dir set to e.g. public), with a local extensions folder at <project-root>/packages/.
- Require
typo3/testing-framework and copy UnitTestsBootstrap.php per the documented setup.
- Run
vendor/bin/phpunit -c <your-unit-tests-config>.xml, even with zero test cases.
- Observe
<project-root>/packages/autoload/{autoload_classmap.php,autoload_psr4.php,autoload_files.php,autoload_classaliasmap.php} being created.
Expected behavior
No classic-mode autoload dump should happen in composer mode, consistent with how typo3/cms-core treats this everywhere else.
Suggested fix
Guard Testbase::dumpClassLoadingInformation() with Environment::isComposerMode(), mirroring the guard used in typo3/cms-core's own call sites. Patch attached / PR to follow:
public function dumpClassLoadingInformation(): void
{
+ if (Environment::isComposerMode()) {
+ return;
+ }
if (!ClassLoadingInformation::isClassLoadingInformationAvailable()) {
ClassLoadingInformation::dumpClassLoadingInformation();
ClassLoadingInformation::registerClassLoadingInformation();
}
}
(plus use TYPO3\CMS\Core\Core\Environment;)
Specify some data of the environment
- TYPO3 testing framework version: 9.5.0
- TYPO3 version: 14.3.4
- TYPO3 installation type: composer
- PHP version: 8.4
- Web server used + version: Apache 2.4.67 (Debian)
- Operating system: Linux Debian
Testbase::dumpClassLoadingInformation()(Classes/Core/Testbase.php:767-773) is called unconditionally fromResources/Core/Build/UnitTestsBootstrap.php(and internally fromsetUpBasicTypo3Bootstrap()for functional tests), with no check for composer mode:Every other caller of this functionality in typo3/cms-core (
DumpAutoloadCommand,MaintenanceController,SetupService,ClassLoadingInformationUpdater) guards it with!Environment::isComposerMode(), since dumping classic-mode autoload info is meaningless when Composer's own autoloader is authoritative. This one call site doesn't, so everyphpunitrun using the shippedUnitTestsBootstrap.php(or any functional test) dumpsautoload_classmap.php,autoload_psr4.php,autoload_files.php,autoload_classaliasmap.phpintoClassLoadingInformation::getClassLoadingInformationDirectory().In a composer-mode project using the "new directory structure" (project root ≠ public web root), that directory resolves to
<project-root>/packages/autoload/(TYPO3\CMS\Core\Core\Environment::$extensionsBasePath = $projectPath . '/packages/ext', andClassLoadingInformationderives its dump dir fromdirname()of that path). Many TYPO3 projects — including the pattern documented in TYPO3's own Composer best-practices guide — use exactlypackages/at the project root for their own local extensions (symlinked via a composer path repository), so every test run leaves an untracked, uncommittedpackages/autoload/directory sitting next to the project's real local extensions.GuardDumpClassLoadingInformationInComposerMode.patch
Steps to reproduce
extra."typo3/cms".web-dirset to e.g.public), with a local extensions folder at<project-root>/packages/.typo3/testing-frameworkand copyUnitTestsBootstrap.phpper the documented setup.vendor/bin/phpunit -c <your-unit-tests-config>.xml, even with zero test cases.<project-root>/packages/autoload/{autoload_classmap.php,autoload_psr4.php,autoload_files.php,autoload_classaliasmap.php}being created.Expected behavior
No classic-mode autoload dump should happen in composer mode, consistent with how
typo3/cms-coretreats this everywhere else.Suggested fix
Guard
Testbase::dumpClassLoadingInformation()withEnvironment::isComposerMode(), mirroring the guard used intypo3/cms-core's own call sites. Patch attached / PR to follow:public function dumpClassLoadingInformation(): void { + if (Environment::isComposerMode()) { + return; + } if (!ClassLoadingInformation::isClassLoadingInformationAvailable()) { ClassLoadingInformation::dumpClassLoadingInformation(); ClassLoadingInformation::registerClassLoadingInformation(); } }(plus
use TYPO3\CMS\Core\Core\Environment;)Specify some data of the environment