1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Tests finder 19 * 20 * @package core 21 * @category test 22 * @copyright 2012 Petr Skoda {@link http://skodak.org} 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 /** 27 * Finds components and plugins with tests 28 * 29 * @package core 30 * @category test 31 * @copyright 2012 Petr Skoda {@link http://skodak.org} 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 */ 34 class tests_finder { 35 36 /** 37 * Returns all the components with tests of the specified type 38 * @param string $testtype The kind of test we are looking for 39 * @return array 40 */ 41 public static function get_components_with_tests($testtype) { 42 43 // Get all the components 44 $components = self::get_all_plugins_with_tests($testtype) + self::get_all_subsystems_with_tests($testtype); 45 46 // Get all the directories having tests 47 $directories = self::get_all_directories_with_tests($testtype); 48 49 // Find any directory not covered by proper components 50 $remaining = array_diff($directories, $components); 51 52 // Add them to the list of components 53 $components += $remaining; 54 55 return $components; 56 } 57 58 /** 59 * Returns all the plugins having tests 60 * @param string $testtype The kind of test we are looking for 61 * @return array all the plugins having tests 62 */ 63 private static function get_all_plugins_with_tests($testtype) { 64 $pluginswithtests = array(); 65 66 $plugintypes = core_component::get_plugin_types(); 67 ksort($plugintypes); 68 foreach ($plugintypes as $type => $unused) { 69 $plugs = core_component::get_plugin_list($type); 70 ksort($plugs); 71 foreach ($plugs as $plug => $fullplug) { 72 // Look for tests recursively 73 if (self::directory_has_tests($fullplug, $testtype)) { 74 $pluginswithtests[$type . '_' . $plug] = $fullplug; 75 } 76 } 77 } 78 return $pluginswithtests; 79 } 80 81 /** 82 * Returns all the subsystems having tests 83 * 84 * Note we are hacking here the list of subsystems 85 * to cover some well-known subsystems that are not properly 86 * returned by the {@link get_core_subsystems()} function. 87 * 88 * @param string $testtype The kind of test we are looking for 89 * @return array all the subsystems having tests 90 */ 91 private static function get_all_subsystems_with_tests($testtype) { 92 global $CFG; 93 94 $subsystemswithtests = array(); 95 96 $subsystems = core_component::get_core_subsystems(); 97 98 // Hack the list a bit to cover some well-known ones 99 $subsystems['backup'] = $CFG->dirroot.'/backup'; 100 $subsystems['db-dml'] = $CFG->dirroot.'/lib/dml'; 101 $subsystems['db-ddl'] = $CFG->dirroot.'/lib/ddl'; 102 103 ksort($subsystems); 104 foreach ($subsystems as $subsys => $fullsubsys) { 105 if ($fullsubsys === null) { 106 continue; 107 } 108 if (!is_dir($fullsubsys)) { 109 continue; 110 } 111 // Look for tests recursively 112 if (self::directory_has_tests($fullsubsys, $testtype)) { 113 $subsystemswithtests['core_' . $subsys] = $fullsubsys; 114 } 115 } 116 return $subsystemswithtests; 117 } 118 119 /** 120 * Returns all the directories having tests 121 * 122 * @param string $testtype The kind of test we are looking for 123 * @return array all directories having tests 124 */ 125 private static function get_all_directories_with_tests($testtype) { 126 global $CFG; 127 128 // List of directories to exclude from test file searching. 129 $excludedir = array('node_modules', 'vendor'); 130 131 // Get first level directories in which tests should be searched. 132 $directoriestosearch = array(); 133 $alldirs = glob($CFG->dirroot . DIRECTORY_SEPARATOR . '*' , GLOB_ONLYDIR); 134 foreach ($alldirs as $dir) { 135 if (!in_array(basename($dir), $excludedir) && (filetype($dir) != 'link')) { 136 $directoriestosearch[] = $dir; 137 } 138 } 139 140 // Search for tests in valid directories. 141 $dirs = array(); 142 foreach ($directoriestosearch as $dir) { 143 $dirite = new RecursiveDirectoryIterator($dir); 144 $iteite = new RecursiveIteratorIterator($dirite); 145 $regexp = self::get_regexp($testtype); 146 $regite = new RegexIterator($iteite, $regexp); 147 foreach ($regite as $path => $element) { 148 $key = dirname(dirname($path)); 149 $value = trim(str_replace(DIRECTORY_SEPARATOR, '_', str_replace($CFG->dirroot, '', $key)), '_'); 150 $dirs[$key] = $value; 151 } 152 } 153 ksort($dirs); 154 return array_flip($dirs); 155 } 156 157 /** 158 * Returns if a given directory has tests (recursively) 159 * 160 * @param string $dir full path to the directory to look for phpunit tests 161 * @param string $testtype phpunit|behat 162 * @return bool if a given directory has tests (true) or no (false) 163 */ 164 private static function directory_has_tests($dir, $testtype) { 165 if (!is_dir($dir)) { 166 return false; 167 } 168 169 $dirite = new RecursiveDirectoryIterator($dir); 170 $iteite = new RecursiveIteratorIterator($dirite); 171 $regexp = self::get_regexp($testtype); 172 $regite = new RegexIterator($iteite, $regexp); 173 $regite->rewind(); 174 if ($regite->valid()) { 175 return true; 176 } 177 return false; 178 } 179 180 181 /** 182 * Returns the regular expression to match by the test files 183 * @param string $testtype 184 * @return string 185 */ 186 private static function get_regexp($testtype) { 187 188 $sep = preg_quote(DIRECTORY_SEPARATOR, '|'); 189 190 switch ($testtype) { 191 case 'phpunit': 192 $regexp = '|'.$sep.'tests'.$sep.'.*_test\.php$|'; 193 break; 194 case 'features': 195 $regexp = '|'.$sep.'tests'.$sep.'behat'.$sep.'.*\.feature$|'; 196 break; 197 case 'stepsdefinitions': 198 $regexp = '|'.$sep.'tests'.$sep.'behat'.$sep.'behat_.*\.php$|'; 199 break; 200 case 'behat': 201 $regexp = '!'.$sep.'tests'.$sep.'behat'.$sep.'(.*\.feature)|(behat_.*\.php)$!'; 202 break; 203 } 204 205 return $regexp; 206 } 207 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body