You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

207 lines
7.0 KiB

<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Tests finder
*
* @package core
* @category test
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Finds components and plugins with tests
*
* @package core
* @category test
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tests_finder {
/**
* Returns all the components with tests of the specified type
* @param string $testtype The kind of test we are looking for
* @return array
*/
public static function get_components_with_tests($testtype) {
// Get all the components
$components = self::get_all_plugins_with_tests($testtype) + self::get_all_subsystems_with_tests($testtype);
// Get all the directories having tests
$directories = self::get_all_directories_with_tests($testtype);
// Find any directory not covered by proper components
$remaining = array_diff($directories, $components);
// Add them to the list of components
$components += $remaining;
return $components;
}
/**
* Returns all the plugins having tests
* @param string $testtype The kind of test we are looking for
* @return array all the plugins having tests
*/
private static function get_all_plugins_with_tests($testtype) {
$pluginswithtests = array();
$plugintypes = core_component::get_plugin_types();
ksort($plugintypes);
foreach ($plugintypes as $type => $unused) {
$plugs = core_component::get_plugin_list($type);
ksort($plugs);
foreach ($plugs as $plug => $fullplug) {
// Look for tests recursively
if (self::directory_has_tests($fullplug, $testtype)) {
$pluginswithtests[$type . '_' . $plug] = $fullplug;
}
}
}
return $pluginswithtests;
}
/**
* Returns all the subsystems having tests
*
* Note we are hacking here the list of subsystems
* to cover some well-known subsystems that are not properly
* returned by the {@link get_core_subsystems()} function.
*
* @param string $testtype The kind of test we are looking for
* @return array all the subsystems having tests
*/
private static function get_all_subsystems_with_tests($testtype) {
global $CFG;
$subsystemswithtests = array();
$subsystems = core_component::get_core_subsystems();
// Hack the list a bit to cover some well-known ones
$subsystems['backup'] = $CFG->dirroot.'/backup';
$subsystems['db-dml'] = $CFG->dirroot.'/lib/dml';
$subsystems['db-ddl'] = $CFG->dirroot.'/lib/ddl';
ksort($subsystems);
foreach ($subsystems as $subsys => $fullsubsys) {
if ($fullsubsys === null) {
continue;
}
if (!is_dir($fullsubsys)) {
continue;
}
// Look for tests recursively
if (self::directory_has_tests($fullsubsys, $testtype)) {
$subsystemswithtests['core_' . $subsys] = $fullsubsys;
}
}
return $subsystemswithtests;
}
/**
* Returns all the directories having tests
*
* @param string $testtype The kind of test we are looking for
* @return array all directories having tests
*/
private static function get_all_directories_with_tests($testtype) {
global $CFG;
// List of directories to exclude from test file searching.
$excludedir = array('node_modules', 'vendor');
// Get first level directories in which tests should be searched.
$directoriestosearch = array();
$alldirs = glob($CFG->dirroot . DIRECTORY_SEPARATOR . '*' , GLOB_ONLYDIR);
foreach ($alldirs as $dir) {
if (!in_array(basename($dir), $excludedir) && (filetype($dir) != 'link')) {
$directoriestosearch[] = $dir;
}
}
// Search for tests in valid directories.
$dirs = array();
foreach ($directoriestosearch as $dir) {
$dirite = new RecursiveDirectoryIterator($dir);
$iteite = new RecursiveIteratorIterator($dirite);
$regexp = self::get_regexp($testtype);
$regite = new RegexIterator($iteite, $regexp);
foreach ($regite as $path => $element) {
$key = dirname(dirname($path));
$value = trim(str_replace(DIRECTORY_SEPARATOR, '_', str_replace($CFG->dirroot, '', $key)), '_');
$dirs[$key] = $value;
}
}
ksort($dirs);
return array_flip($dirs);
}
/**
* Returns if a given directory has tests (recursively)
*
* @param string $dir full path to the directory to look for phpunit tests
* @param string $testtype phpunit|behat
* @return bool if a given directory has tests (true) or no (false)
*/
private static function directory_has_tests($dir, $testtype) {
if (!is_dir($dir)) {
return false;
}
$dirite = new RecursiveDirectoryIterator($dir);
$iteite = new RecursiveIteratorIterator($dirite);
$regexp = self::get_regexp($testtype);
$regite = new RegexIterator($iteite, $regexp);
$regite->rewind();
if ($regite->valid()) {
return true;
}
return false;
}
/**
* Returns the regular expression to match by the test files
* @param string $testtype
* @return string
*/
private static function get_regexp($testtype) {
$sep = preg_quote(DIRECTORY_SEPARATOR, '|');
switch ($testtype) {
case 'phpunit':
$regexp = '|'.$sep.'tests'.$sep.'.*_test\.php$|';
break;
case 'features':
$regexp = '|'.$sep.'tests'.$sep.'behat'.$sep.'.*\.feature$|';
break;
case 'stepsdefinitions':
$regexp = '|'.$sep.'tests'.$sep.'behat'.$sep.'behat_.*\.php$|';
break;
case 'behat':
$regexp = '!'.$sep.'tests'.$sep.'behat'.$sep.'(.*\.feature)|(behat_.*\.php)$!';
break;
}
return $regexp;
}
}