Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
}