5 * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.de>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
20 * * Neither the name of Sebastian Bergmann nor the names of his
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
39 * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
40 * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
41 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43 * @link http://www.phpunit.de/
44 * @since File available since Release 3.2.0
47 require_once 'PHPUnit/Util/Filter.php';
48 require_once 'PHPUnit/Runner/IncludePathTestCollector.php';
49 require_once 'PHPUnit/Util/XML.php';
51 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
54 * Wrapper for the PHPUnit XML configuration file.
56 * Example XML configuration file:
58 * <?xml version="1.0" encoding="utf-8" ?>
60 * <phpunit bootstrap="/path/to/bootstrap.php"
62 * convertErrorsToExceptions="true"
63 * convertNoticesToExceptions="true"
64 * convertWarningsToExceptions="true"
65 * stopOnFailure="false">
66 * <testsuite name="My Test Suite">
67 * <directory suffix="Test.php">/path/to/files</directory>
68 * <file>/path/to/MyTest.php</file>
82 * <directory suffix=".php">/path/to/files</directory>
83 * <file>/path/to/file</file>
85 * <directory suffix=".php">/path/to/files</directory>
86 * <file>/path/to/file</file>
89 * <whitelist addUncoveredFilesFromWhitelist="true">
90 * <directory suffix=".php">/path/to/files</directory>
91 * <file>/path/to/file</file>
93 * <directory suffix=".php">/path/to/files</directory>
94 * <file>/path/to/file</file>
100 * <log type="coverage-html" target="/tmp/report" charset="UTF-8"
101 * yui="true" highlight="false"
102 * lowUpperBound="35" highLowerBound="70"/>
103 * <log type="coverage-clover" target="/tmp/clover.xml"/>
104 * <log type="coverage-source" target="/tmp/coverage"/>
105 * <log type="graphviz" target="/tmp/logfile.dot"/>
106 * <log type="json" target="/tmp/logfile.json"/>
107 * <log type="metrics-xml" target="/tmp/metrics.xml"/>
108 * <log type="plain" target="/tmp/logfile.txt"/>
109 * <log type="pmd-xml" target="/tmp/pmd.xml" cpdMinLines="5" cpdMinMatches="70"/>
110 * <log type="tap" target="/tmp/logfile.tap"/>
111 * <log type="test-xml" target="/tmp/logfile.xml" logIncompleteSkipped="false"/>
112 * <log type="story-html" target="/tmp/story.html"/>
113 * <log type="story-text" target="/tmp/story.txt"/>
114 * <log type="testdox-html" target="/tmp/testdox.html"/>
115 * <log type="testdox-text" target="/tmp/testdox.txt"/>
118 * <rule class="PHPUnit_Util_Log_PMD_Rule_Project_CRAP"
119 * threshold="5,30" priority="1"/>
120 * <rule class="PHPUnit_Util_Log_PMD_Rule_Class_DepthOfInheritanceTree"
121 * threshold="6" priority="1"/>
122 * <rule class="PHPUnit_Util_Log_PMD_Rule_Class_EfferentCoupling"
123 * threshold="20" priority="1"/>
124 * <rule class="PHPUnit_Util_Log_PMD_Rule_Class_ExcessiveClassLength"
125 * threshold="1000" priority="1"/>
126 * <rule class="PHPUnit_Util_Log_PMD_Rule_Class_ExcessivePublicCount"
127 * threshold="45" priority="1"/>
128 * <rule class="PHPUnit_Util_Log_PMD_Rule_Class_TooManyFields"
129 * threshold="15" priority="1"/>
130 * <rule class="PHPUnit_Util_Log_PMD_Rule_Function_CodeCoverage"
131 * threshold="35,70" priority="1"/>
132 * <rule class="PHPUnit_Util_Log_PMD_Rule_Function_CRAP"
133 * threshold="30" priority="1"/>
134 * <rule class="PHPUnit_Util_Log_PMD_Rule_Function_CyclomaticComplexity"
135 * threshold="20" priority="1"/>
136 * <rule class="PHPUnit_Util_Log_PMD_Rule_Function_ExcessiveMethodLength"
137 * threshold="100" priority="1"/>
138 * <rule class="PHPUnit_Util_Log_PMD_Rule_Function_ExcessiveParameterList"
139 * threshold="10" priority="1"/>
140 * <rule class="PHPUnit_Util_Log_PMD_Rule_Function_NPathComplexity"
141 * threshold="200" priority="1"/>
146 * <ini name="foo" value="bar"/>
147 * <var name="foo" value="bar"/>
151 * <browser name="Firefox on Linux"
152 * browser="*firefox /usr/lib/firefox/firefox-bin"
153 * host="my.linux.box"
162 * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
163 * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
164 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
165 * @version Release: 3.3.17
166 * @link http://www.phpunit.de/
167 * @since Class available since Release 3.2.0
169 class PHPUnit_Util_Configuration
175 * Loads a PHPUnit configuration file.
177 * @param string $filename
179 public function __construct($filename)
181 $this->document = PHPUnit_Util_XML::loadFile($filename);
182 $this->xpath = new DOMXPath($this->document);
186 * Returns the configuration for SUT filtering.
189 * @since Method available since Release 3.2.1
191 public function getFilterConfiguration()
193 $addUncoveredFilesFromWhitelist = TRUE;
195 $tmp = $this->xpath->query('filter/whitelist');
197 if ($tmp->length == 1 &&
198 $tmp->item(0)->hasAttribute('addUncoveredFilesFromWhitelist')) {
199 $addUncoveredFilesFromWhitelist = $this->getBoolean(
200 (string)$tmp->item(0)->getAttribute('addUncoveredFilesFromWhitelist'),
206 'blacklist' => array(
208 'directory' => $this->readFilterDirectories(
209 'filter/blacklist/directory'
211 'file' => $this->readFilterFiles(
212 'filter/blacklist/file'
216 'directory' => $this->readFilterDirectories(
217 'filter/blacklist/exclude/directory'
219 'file' => $this->readFilterFiles(
220 'filter/blacklist/exclude/file'
224 'whitelist' => array(
225 'addUncoveredFilesFromWhitelist' => $addUncoveredFilesFromWhitelist,
227 'directory' => $this->readFilterDirectories(
228 'filter/whitelist/directory'
230 'file' => $this->readFilterFiles(
231 'filter/whitelist/file'
235 'directory' => $this->readFilterDirectories(
236 'filter/whitelist/exclude/directory'
238 'file' => $this->readFilterFiles(
239 'filter/whitelist/exclude/file'
247 * Returns the configuration for groups.
250 * @since Method available since Release 3.2.1
252 public function getGroupConfiguration()
255 'include' => array(),
259 foreach ($this->xpath->query('groups/include/group') as $group) {
260 $groups['include'][] = (string)$group->nodeValue;
263 foreach ($this->xpath->query('groups/exclude/group') as $group) {
264 $groups['exclude'][] = (string)$group->nodeValue;
271 * Returns the logging configuration.
275 public function getLoggingConfiguration()
279 foreach ($this->xpath->query('logging/log') as $log) {
280 $type = (string)$log->getAttribute('type');
281 $target = (string)$log->getAttribute('target');
283 if ($type == 'coverage-html') {
284 if ($log->hasAttribute('charset')) {
285 $result['charset'] = (string)$log->getAttribute('charset');
288 if ($log->hasAttribute('lowUpperBound')) {
289 $result['lowUpperBound'] = (string)$log->getAttribute('lowUpperBound');
292 if ($log->hasAttribute('highLowerBound')) {
293 $result['highLowerBound'] = (string)$log->getAttribute('highLowerBound');
296 if ($log->hasAttribute('yui')) {
297 $result['yui'] = $this->getBoolean(
298 (string)$log->getAttribute('yui'),
303 if ($log->hasAttribute('highlight')) {
304 $result['highlight'] = $this->getBoolean(
305 (string)$log->getAttribute('highlight'),
311 else if ($type == 'pmd-xml') {
312 if ($log->hasAttribute('cpdMinLines')) {
313 $result['cpdMinLines'] = (string)$log->getAttribute('cpdMinLines');
316 if ($log->hasAttribute('cpdMinMatches')) {
317 $result['cpdMinMatches'] = (string)$log->getAttribute('cpdMinMatches');
321 else if ($type == 'test-xml') {
322 if ($log->hasAttribute('logIncompleteSkipped')) {
323 $result['logIncompleteSkipped'] = $this->getBoolean(
324 (string)$log->getAttribute('logIncompleteSkipped'),
330 $result[$type] = $target;
337 * Returns the PHP configuration.
340 * @since Method available since Release 3.2.1
342 public function getPHPConfiguration()
349 foreach ($this->xpath->query('php/ini') as $ini) {
350 $name = (string)$ini->getAttribute('name');
351 $value = (string)$ini->getAttribute('value');
353 $result['ini'][$name] = $value;
356 foreach ($this->xpath->query('php/var') as $var) {
357 $name = (string)$var->getAttribute('name');
358 $value = (string)$var->getAttribute('value');
360 if (strtolower($value) == 'false') {
364 else if (strtolower($value) == 'true') {
368 $result['var'][$name] = $value;
375 * Handles the PHP configuration.
377 * @since Method available since Release 3.2.20
379 public function handlePHPConfiguration()
381 $configuration = $this->getPHPConfiguration();
383 foreach ($configuration['ini'] as $name => $value) {
384 if (defined($value)) {
385 $value = constant($value);
388 ini_set($name, $value);
391 foreach ($configuration['var'] as $name => $value) {
392 $GLOBALS[$name] = $value;
397 * Returns the PHPUnit configuration.
400 * @since Method available since Release 3.2.14
402 public function getPHPUnitConfiguration()
406 if ($this->document->documentElement->hasAttribute('colors')) {
407 $result['colors'] = $this->getBoolean(
408 (string)$this->document->documentElement->getAttribute('colors'),
413 else if ($this->document->documentElement->hasAttribute('ansi')) {
414 $result['colors'] = $this->getBoolean(
415 (string)$this->document->documentElement->getAttribute('ansi'),
420 if ($this->document->documentElement->hasAttribute('bootstrap')) {
421 $result['bootstrap'] = (string)$this->document->documentElement->getAttribute('bootstrap');
424 if ($this->document->documentElement->hasAttribute('convertErrorsToExceptions')) {
425 $result['convertErrorsToExceptions'] = $this->getBoolean(
426 (string)$this->document->documentElement->getAttribute('convertErrorsToExceptions'),
431 if ($this->document->documentElement->hasAttribute('convertNoticesToExceptions')) {
432 $result['convertNoticesToExceptions'] = $this->getBoolean(
433 (string)$this->document->documentElement->getAttribute('convertNoticesToExceptions'),
438 if ($this->document->documentElement->hasAttribute('convertWarningsToExceptions')) {
439 $result['convertWarningsToExceptions'] = $this->getBoolean(
440 (string)$this->document->documentElement->getAttribute('convertWarningsToExceptions'),
445 if ($this->document->documentElement->hasAttribute('stopOnFailure')) {
446 $result['stopOnFailure'] = $this->getBoolean(
447 (string)$this->document->documentElement->getAttribute('stopOnFailure'),
456 * Returns the configuration for PMD rules.
460 public function getPMDConfiguration()
464 foreach ($this->xpath->query('logging/pmd/rule') as $rule) {
465 $class = (string)$rule->getAttribute('class');
467 $threshold = (string)$rule->getAttribute('threshold');
468 $threshold = explode(',', $threshold);
470 if (count($threshold) == 1) {
471 $threshold = $threshold[0];
474 $priority = (int)$rule->getAttribute('priority');
476 $result[$class] = array(
477 'threshold' => $threshold,
478 'priority' => $priority
486 * Returns the SeleniumTestCase browser configuration.
489 * @since Method available since Release 3.2.9
491 public function getSeleniumBrowserConfiguration()
495 foreach ($this->xpath->query('selenium/browser') as $config) {
496 $name = (string)$config->getAttribute('name');
497 $browser = (string)$config->getAttribute('browser');
499 if ($config->hasAttribute('host')) {
500 $host = (string)$config->getAttribute('host');
505 if ($config->hasAttribute('port')) {
506 $port = (int)$config->getAttribute('port');
511 if ($config->hasAttribute('timeout')) {
512 $timeout = (int)$config->getAttribute('timeout');
519 'browser' => $browser,
522 'timeout' => $timeout
530 * Returns the test suite configuration.
532 * @param boolean $syntaxCheck
533 * @return PHPUnit_Framework_TestSuite
534 * @since Method available since Release 3.2.1
536 public function getTestSuiteConfiguration($syntaxCheck = TRUE)
538 $testSuiteNode = $this->xpath->query('testsuite');
540 if ($testSuiteNode->length > 0) {
541 $testSuiteNode = $testSuiteNode->item(0);
543 if ($testSuiteNode->hasAttribute('name')) {
544 $suite = new PHPUnit_Framework_TestSuite(
545 (string)$testSuiteNode->getAttribute('name')
548 $suite = new PHPUnit_Framework_TestSuite;
551 foreach ($this->xpath->query('testsuite/directory') as $directoryNode) {
552 if ($directoryNode->hasAttribute('suffix')) {
553 $suffix = (string)$directoryNode->getAttribute('suffix');
555 $suffix = 'Test.php';
558 $testCollector = new PHPUnit_Runner_IncludePathTestCollector(
559 array((string)$directoryNode->nodeValue),
563 $suite->addTestFiles(
564 $testCollector->collectTests(), $syntaxCheck
568 foreach ($this->xpath->query('testsuite/file') as $fileNode) {
569 $suite->addTestFile((string)$fileNode->nodeValue, $syntaxCheck);
577 * @param string $value
578 * @param boolean $default
580 * @since Method available since Release 3.2.3
582 protected function getBoolean($value, $default)
584 if (strtolower($value) == 'false') {
588 else if (strtolower($value) == 'true') {
596 * @param string $query
598 * @since Method available since Release 3.2.3
600 protected function readFilterDirectories($query)
602 $directories = array();
604 foreach ($this->xpath->query($query) as $directory) {
605 if ($directory->hasAttribute('suffix')) {
606 $suffix = (string)$directory->getAttribute('suffix');
611 $directories[] = array(
612 'path' => (string)$directory->nodeValue,
621 * @param string $query
623 * @since Method available since Release 3.2.3
625 protected function readFilterFiles($query)
629 foreach ($this->xpath->query($query) as $file) {
630 $files[] = (string)$file->nodeValue;