Hi all,
I wanted to quickly announce two new classes I added to MediaWiki core the other day: ExtensionServicesTestBase https://gerrit.wikimedia.org/g/mediawiki/core/+/master/tests/phpunit/integration/includes/ExtensionServicesTestBase.php and ExtensionJsonTestBase https://gerrit.wikimedia.org/g/mediawiki/core/+/master/tests/phpunit/integration/includes/ExtensionJsonTestBase.php. Both are abstract base classes for PHPUnit tests; by adding a test class extending one of these base classes, an extension can *opt into* additional tests, with very little extra code in the extension itself. If you don’t want to do that, nothing will change for you :)
ExtensionServicesTestBase can be used to test “ExtensionServices” classes (e.g. CognateServices or WikibaseRepo). These classes are described on mw:Dependency Injection § Service registration in extensions https://www.mediawiki.org/wiki/Dependency_Injection#Service_registration_in_extensions; basically, they’re a bunch of boilerplate code that makes an extension’s services in the service container easier to work with ( CognateServices::getStore() is equivalent to $services->getService( 'CognateStore' ), but the former can be autosuggested by the IDE and also has a known return type). An ExtensionServicesTestBase subclass tests that this boilerplate code looks like you’d expect it to: the methods are static, their name matches the service name, etc. Nothing exciting, but nice to have if you use this “ExtensionServices” pattern.
ExtensionJsonTestBase is more exciting. The tests in this class read your extension.json, and try to create the various API modules, special pages, etc. that are specified in there, according to their factory specifications. This ensures, for instance, that the list of services specified in extension.json actually matches what the configured constructor or factory method expects (e.g. in case you added a service to the constructor and your unit test, but forgot to add it to extension.json), which might otherwise only be caught by browser tests (even integration tests don’t usually use the extension.json factories). More importantly, the tests also ensure that no HTTP or database connections are made when all these things are created. Services that make network requests as soon as they’re created, rather than only when they’re used, have been a performance issue in Wikibase in the past (T243729 https://phabricator.wikimedia.org/T243729), and these tests are meant to prevent such a thing from happening again.
(In theory, all of this might work more or less well for skins as well as extensions. I have no reason to try that, since I don’t work on skins, but if you’re interested in it, feel free to experiment with it and see if it works out. I’ll point out that MediaWiki’s ExtensionJsonValidationTest, which “Validates all loaded extensions and skins using the ExtensionRegistry against the extension.json schema in the docs/ folder”, could be a precedent for an “ExtensionSomething” class actually covering both extensions and skins, so I don’t think the two new TestBase classes would necessarily need to be renamed.)
A minimal example of using both of these tests in an extension might look like this:
class EntitySchemaServicesTest extends ExtensionServicesTestBase { protected string $className = EntitySchemaServices::class; protected string $serviceNamePrefix = 'EntitySchema.'; }
class EntitySchemaExtensionJsonTest extends ExtensionJsonTestBase { protected string $extensionJsonPath = __DIR__ . '/../../../../extension.json'; }
Cheers, Lucas
wikitech-l@lists.wikimedia.org