Allow specifying autoloaded classes for tests

This introduces two new keys to the extension schema, analogous to
the existing autoloader keys: TestAutoloadNamespaces and
TestAutoloadClasses.

The classes and namespaces defined by these keys are only loaded by
the registry when ExtensionRegistry::setLoadTestClassesAndNamespaces
is called. The phpunit wrapper does this in PHPUnitMaintClass::setup.
The unit test bootstrap file calls
ExtensionRegistry::exportTestAutoloadClassesAndNamespaces instead,
similar to how it loads the regular classes and namespaces.

Bug: T196090
Change-Id: I88cf69663362fd599c20649b1df641907a02678d
This commit is contained in:
mainframe98 2019-12-10 13:13:13 +01:00 committed by Catrope
parent 554feecbb4
commit ac48c84224
6 changed files with 82 additions and 0 deletions

View file

@ -65,6 +65,9 @@ For notes on 1.34.x and older releases, see HISTORY.
* If CSP is enabled, extensions can now add additional sources using the
ContentSecurityPolicy::addDefaultSource, ::addStyleSrc and ::addScriptSrc
methods (e.g. $context->getOutput()->getCSP()->addDefaultSrc( 'example.com' ))
* Extensions can now specify classes and namespaces to be autoloaded by the
test autoloader, by setting the "TestAutoloadNamespaces" and
"TestAutoloadClasses" properties in extension.json. (T196090)
* …
=== External library changes in 1.35 ===

View file

@ -662,6 +662,19 @@
"AutoloadClasses": {
"type": "object"
},
"TestAutoloadNamespaces": {
"type": "object",
"description": "Mapping of PSR-4 compliant namespace to directory for autoloading to be used in tests",
"patternProperties": {
"^[A-Za-z0-9\\\\]+\\\\$": {
"type": "string"
}
},
"additionalProperties": false
},
"TestAutoloadClasses": {
"type": "object"
},
"Hooks": {
"type": [ "string", "object" ],
"description": "Hooks this extension uses (mapping of hook name to callback)"

View file

@ -767,6 +767,19 @@
"AutoloadClasses": {
"type": "object"
},
"TestAutoloadNamespaces": {
"type": "object",
"description": "Mapping of PSR-4 compliant namespace to directory for autoloading to be used in tests",
"patternProperties": {
"^[A-Za-z0-9\\\\]+\\\\$": {
"type": "string"
}
},
"additionalProperties": false
},
"TestAutoloadClasses": {
"type": "object"
},
"Hooks": {
"type": [ "string", "object" ],
"description": "Hooks this extension uses (mapping of hook name to callback)"

View file

@ -94,6 +94,13 @@ class ExtensionRegistry {
*/
protected $checkDev = false;
/**
* Whether test classes and namespaces should be added to the auto loader
*
* @var bool
*/
protected $loadTestClassesAndNamespaces = false;
/**
* @var ExtensionRegistry
*/
@ -119,6 +126,17 @@ class ExtensionRegistry {
$this->checkDev = $check;
}
/**
* Controls if classes and namespaces defined under the keys TestAutoloadClasses and
* TestAutloadNamespaces should be added to the autoloader.
*
* @since 1.35
* @param bool $load
*/
public function setLoadTestClassesAndNamespaces( $load ) {
$this->loadTestClassesAndNamespaces = $load;
}
/**
* @param string $path Absolute path to the JSON file
*/
@ -304,6 +322,15 @@ class ExtensionRegistry {
$autoloadNamespaces
);
if ( $this->loadTestClassesAndNamespaces ) {
self::exportTestAutoloadClassesAndNamespaces(
$dir,
$info,
$autoloadClasses,
$autoloadNamespaces
);
}
// get all requirements/dependencies for this extension
$requires = $processor->getRequirements( $info, $this->checkDev );
@ -360,6 +387,29 @@ class ExtensionRegistry {
}
}
/**
* Export test autoload classes and namespaces for a given directory and parsed JSON info file.
*
* @since 1.35
* @param string $dir
* @param array $info
* @param array &$autoloadClasses
* @param array &$autoloadNamespaces
*/
public static function exportTestAutoloadClassesAndNamespaces(
$dir, $info, &$autoloadClasses = [], &$autoloadNamespaces = []
) {
if ( isset( $info['TestAutoloadClasses'] ) ) {
$autoload = self::processAutoLoader( $dir, $info['TestAutoloadClasses'] );
$GLOBALS['wgAutoloadClasses'] += $autoload;
$autoloadClasses += $autoload;
}
if ( isset( $info['TestAutoloadNamespaces'] ) ) {
$autoloadNamespaces += self::processAutoLoader( $dir, $info['TestAutoloadNamespaces'] );
AutoLoader::$psr4Namespaces += $autoloadNamespaces;
}
}
protected function exportExtractedData( array $info ) {
foreach ( $info['globals'] as $key => $val ) {
// If a merge strategy is set, read it and remove it from the value

View file

@ -87,6 +87,7 @@ foreach ( $directoryToJsonMap as $directory => $jsonFile ) {
$info = json_decode( $json, true );
$dir = dirname( $jsonPath );
ExtensionRegistry::exportAutoloadClassesAndNamespaces( $dir, $info );
ExtensionRegistry::exportTestAutoloadClassesAndNamespaces( $dir, $info );
}
}
}

View file

@ -48,6 +48,8 @@ class PHPUnitMaintClass extends Maintenance {
self::requireTestsAutoloader();
TestSetup::applyInitialConfig();
ExtensionRegistry::getInstance()->setLoadTestClassesAndNamespaces( true );
}
public function execute() {