1
0
قرینه از https://github.com/matomo-org/matomo.git synced 2025-08-21 22:47:43 +00:00
Files
matomo/plugins/TestRunner/Commands/TestsRun.php
Michal Kleiner 9a3ef94df6 [Coding Style] Enable rule PSR12.Files.FileHeader + unify file headers (#22132)
* [Coding Style] Enable rule PSR12.Files.FileHeader

* Apply CS

* Replace Piwik with Matomo in file headers

* Unify file headers (position, no. of lines, https links)

* Rebuild dist files

* Apply CS

* Fix system test that relies on line numbers in a file that had the file header updated

---------

Co-authored-by: Stefan Giehl <stefan@matomo.org>
2024-04-20 20:50:47 +02:00

303 خطوط
10 KiB
PHP

<?php
/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
namespace Piwik\Plugins\TestRunner\Commands;
use Piwik\Db;
use Piwik\Plugin;
use Piwik\Profiler;
use Piwik\Plugin\ConsoleCommand;
/**
* Executes PHP tests.
*/
class TestsRun extends ConsoleCommand
{
private $returnVar = 0;
protected function configure()
{
$this->setName('tests:run');
$this->setDescription('Run Piwik PHPUnit tests one testsuite after the other');
$this->addOptionalArgument('variables', 'Eg a path to a file or directory, the name of a testsuite, the name of a plugin, ... We will try to detect what you meant. You can define multiple values', [], true);
$this->addOptionalValueOption('options', 'o', 'All options will be forwarded to phpunit', '');
$this->addOptionalValueOption('filter', null, 'Adds the phpunit filter option to run only specific tests that start with the given name', '');
$this->addNoValueOption('xhprof', null, 'Profile using xhprof.');
$this->addRequiredValueOption('group', null, 'Run only a specific test group. Separate multiple groups by comma, for instance core,plugins', '');
$this->addRequiredValueOption('file', null, 'Execute tests within this file. Should be a path relative to the tests/PHPUnit directory.');
$this->addRequiredValueOption('testsuite', null, 'Execute tests of a specific test suite, for instance unit, integration or system.');
$this->addNoValueOption('enable-logging', null, 'Enable logging to the configured log file during tests.');
}
protected function doExecute(): int
{
$input = $this->getInput();
$output = $this->getOutput();
$options = $input->getOption('options');
$groups = $input->getOption('group');
$magics = $input->getArgument('variables');
$matomoDomain = $input->getOption('matomo-domain');
$enableLogging = $input->getOption('enable-logging');
$filter = $input->getOption('filter');
if (!empty($filter)) {
$options .= ' --filter=' . escapeshellarg($filter);
}
$groups = $this->getGroupsFromString($groups);
// bin is the composer executeable directory, where all vendors (should) place their executables
$command = PIWIK_VENDOR_PATH . '/bin/phpunit';
if (!$this->isCoverageEnabled($options) && $this->isXdebugLoaded()) {
$message = 'Did you know? You can run tests faster by disabling xdebug';
if ($this->isXdebugCodeCoverageEnabled()) {
$message .= ' (if you need xdebug, speed up tests by setting xdebug.coverage_enable=0)</comment>';
}
$output->writeln('<comment>' . $message . '</comment>');
}
// force xdebug usage for coverage options
if ($this->isCoverageEnabled($options) && !$this->isXdebugLoaded()) {
$output->writeln('<info>xdebug extension required for code coverage.</info>');
$output->writeln('<info>searching for xdebug extension...</info>');
$extensionDir = shell_exec('php-config --extension-dir');
$xdebugFile = trim($extensionDir) . DIRECTORY_SEPARATOR . 'xdebug.so';
if (!file_exists($xdebugFile)) {
$xdebugFile = $this->askAndValidate(
'xdebug not found. Please provide path to xdebug.so',
function ($xdebugFile) {
return file_exists($xdebugFile);
}
);
} else {
$output->writeln('<info>xdebug extension found in extension path.</info>');
}
$output->writeln("<info>using $xdebugFile as xdebug extension.</info>");
$phpunitPath = trim(shell_exec('which phpunit') ?? '');
$command = sprintf('php -d zend_extension=%s %s', $xdebugFile, $phpunitPath);
}
if ($input->getOption('xhprof')) {
Profiler::setupProfilerXHProf($isMainRun = true);
putenv('PIWIK_USE_XHPROF=1');
}
$suite = $this->getTestsuite();
$testFile = $this->getTestFile();
if (!empty($magics)) {
foreach ($magics as $magic) {
if (empty($suite) && (in_array($magic, $this->getTestsSuites()))) {
$suite = $this->buildTestSuiteName($magic);
} elseif (empty($testFile) && 'core' === $magic) {
$testFile = $this->fixPathToTestFileOrDirectory('tests/PHPUnit');
} elseif (empty($testFile) && 'plugins' === $magic) {
$testFile = $this->fixPathToTestFileOrDirectory('plugins');
} elseif (empty($testFile) && file_exists($magic)) {
$testFile = $this->fixPathToTestFileOrDirectory($magic);
} elseif (empty($testFile) && $this->getPluginTestFolderName($magic)) {
$testFile = $this->getPluginTestFolderName($magic);
} elseif (empty($groups)) {
$groups = $this->getGroupsFromString($magic);
} else {
$groups[] = $magic;
}
}
}
// Tear down any DB that already exists
Db::destroyDatabaseObject();
$this->executeTests($matomoDomain, $suite, $testFile, $groups, $options, $command, $enableLogging);
return $this->returnVar;
}
private function getPluginTestFolderName($name)
{
$pluginName = $this->getPluginName($name);
$folder = '';
if (!empty($pluginName)) {
$path = PIWIK_INCLUDE_PATH . '/plugins/' . $pluginName;
if (is_dir($path . '/tests')) {
$folder = $this->fixPathToTestFileOrDirectory($path . '/tests');
} elseif (is_dir($path . '/Tests')) {
$folder = $this->fixPathToTestFileOrDirectory($path . '/Tests');
}
}
return $folder;
}
private function getPluginName($name)
{
$pluginNames = Plugin\Manager::getInstance()->getAllPluginsNames();
foreach ($pluginNames as $pluginName) {
if (strtolower($pluginName) === strtolower($name)) {
return $pluginName;
}
}
}
private function getTestFile()
{
$testFile = $this->getInput()->getOption('file');
if (empty($testFile)) {
return '';
}
return $this->fixPathToTestFileOrDirectory($testFile);
}
private function executeTests($piwikDomain, $suite, $testFile, $groups, $options, $command, $enableLogging)
{
if (empty($suite) && empty($groups) && empty($testFile)) {
foreach ($this->getTestsSuites() as $suite) {
$suite = $this->buildTestSuiteName($suite);
$this->executeTests($piwikDomain, $suite, $testFile, $groups, $options, $command, $enableLogging);
}
return;
}
$params = $this->buildPhpUnitCliParams($suite, $groups, $options);
if (!empty($testFile)) {
$params = $params . " " . $testFile;
}
$this->executeTestRun($piwikDomain, $command, $params, $enableLogging);
}
private function executeTestRun($piwikDomain, $command, $params, $enableLogging)
{
$output = $this->getOutput();
$envVars = '';
if (!empty($piwikDomain)) {
$envVars .= "PIWIK_DOMAIN=$piwikDomain";
}
if (!empty($enableLogging)) {
$envVars .= " MATOMO_TESTS_ENABLE_LOGGING=1";
}
$cmd = $this->getCommand($envVars, $command, $params);
$output->writeln('Executing command: <info>' . $cmd . '</info>');
passthru($cmd, $returnVar);
$output->writeln("");
$this->returnVar += $returnVar;
}
private function getTestsSuites()
{
return array('unit', 'integration', 'system', 'plugin');
}
/**
* @param $command
* @param $params
* @return string
*/
private function getCommand($envVars, $command, $params)
{
return sprintf('cd %s/tests/PHPUnit && %s %s %s', PIWIK_DOCUMENT_ROOT, $envVars, $command, $params);
}
private function buildPhpUnitCliParams($suite, $groups, $options)
{
$params = $options . " ";
if (!empty($groups)) {
$groups = implode(',', $groups);
$params .= '--group ' . $groups . ' ';
} else {
$groups = '';
}
if (!empty($suite)) {
$params .= ' --testsuite ' . $suite;
} else {
$suite = '';
}
$params = str_replace('%suite%', $suite, $params);
$params = str_replace('%group%', $groups, $params);
return $params;
}
private function getTestsuite()
{
$suite = $this->getInput()->getOption('testsuite');
if (empty($suite)) {
return;
}
$availableSuites = $this->getTestsSuites();
if (!in_array($suite, $availableSuites)) {
throw new \InvalidArgumentException('Invalid testsuite specified. Use one of: ' . implode(', ', $availableSuites));
}
$suite = $this->buildTestSuiteName($suite);
return $suite;
}
private function buildTestSuiteName($suite)
{
return ucfirst($suite) . 'Tests';
}
private function isCoverageEnabled($options)
{
return false !== strpos($options, '--coverage');
}
private function isXdebugLoaded()
{
return extension_loaded('xdebug');
}
private function isXdebugCodeCoverageEnabled()
{
return (bool)ini_get('xdebug.coverage_enable');
}
private function fixPathToTestFileOrDirectory($testFile)
{
if ('/' !== substr($testFile, 0, 1)) {
$testFile = '../../' . $testFile;
}
return $testFile;
}
private function getGroupsFromString($groups)
{
$groups = explode(",", $groups);
$groups = array_filter($groups, 'strlen');
return $groups;
}
}