diff options
Diffstat (limited to 'buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTask.php')
-rwxr-xr-x | buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTask.php | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTask.php b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTask.php new file mode 100755 index 00000000..5b842b95 --- /dev/null +++ b/buildscripts/phing/classes/phing/tasks/ext/phpunit/PHPUnitTask.php @@ -0,0 +1,378 @@ +<?php +/** + * $Id: 4554fdd642b6ef7774cbb89c537ccba90f3ca972 $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the LGPL. For more information please see + * <http://phing.info>. + */ + +require_once 'phing/Task.php'; +require_once 'phing/system/io/PhingFile.php'; +require_once 'phing/system/io/Writer.php'; +require_once 'phing/util/LogWriter.php'; + +/** + * Runs PHPUnit tests. + * + * @author Michiel Rook <mrook@php.net> + * @version $Id: 4554fdd642b6ef7774cbb89c537ccba90f3ca972 $ + * @package phing.tasks.ext.phpunit + * @see BatchTest + * @since 2.1.0 + */ +class PHPUnitTask extends Task +{ + private $batchtests = array(); + private $formatters = array(); + private $bootstrap = ""; + private $haltonerror = false; + private $haltonfailure = false; + private $haltonincomplete = false; + private $haltonskipped = false; + private $errorproperty; + private $failureproperty; + private $incompleteproperty; + private $skippedproperty; + private $printsummary = false; + private $testfailed = false; + private $testfailuremessage = ""; + private $codecoverage = null; + private $groups = array(); + private $excludeGroups = array(); + private $processIsolation = false; + private $usecustomerrorhandler = true; + + /** + * Initialize Task. + * This method includes any necessary PHPUnit libraries and triggers + * appropriate error if they cannot be found. This is not done in header + * because we may want this class to be loaded w/o triggering an error. + */ + public function init() { + /** + * Determine PHPUnit version number + */ + @include_once 'PHPUnit/Runner/Version.php'; + + if (!class_exists('PHPUnit_Runner_Version')) { + throw new BuildException("PHPUnitTask requires PHPUnit to be installed", $this->getLocation()); + } + + $version = PHPUnit_Runner_Version::id(); + + if (version_compare($version, '3.6.0') < 0) + { + throw new BuildException("PHPUnitTask requires PHPUnit version >= 3.6.0", $this->getLocation()); + } + + /** + * Other dependencies that should only be loaded when class is actually used. + */ + require_once 'phing/tasks/ext/phpunit/PHPUnitTestRunner.php'; + require_once 'phing/tasks/ext/phpunit/BatchTest.php'; + require_once 'phing/tasks/ext/phpunit/FormatterElement.php'; + + /** + * point PHPUnit_MAIN_METHOD define to non-existing method + */ + if (!defined('PHPUnit_MAIN_METHOD')) + { + define('PHPUnit_MAIN_METHOD', 'PHPUnitTask::undefined'); + } + } + + /** + * Sets the name of a bootstrap file that is run before + * executing the tests + * + * @param string $bootstrap the name of the bootstrap file + */ + public function setBootstrap($bootstrap) + { + $this->bootstrap = $bootstrap; + } + + public function setErrorproperty($value) + { + $this->errorproperty = $value; + } + + public function setFailureproperty($value) + { + $this->failureproperty = $value; + } + + public function setIncompleteproperty($value) + { + $this->incompleteproperty = $value; + } + + public function setSkippedproperty($value) + { + $this->skippedproperty = $value; + } + + public function setHaltonerror($value) + { + $this->haltonerror = $value; + } + + public function setHaltonfailure($value) + { + $this->haltonfailure = $value; + } + + public function getHaltonfailure() + { + return $this->haltonfailure; + } + + public function setHaltonincomplete($value) + { + $this->haltonincomplete = $value; + } + + public function getHaltonincomplete() + { + return $this->haltonincomplete; + } + + public function setHaltonskipped($value) + { + $this->haltonskipped = $value; + } + + public function getHaltonskipped() + { + return $this->haltonskipped; + } + + public function setPrintsummary($printsummary) + { + $this->printsummary = $printsummary; + } + + public function setCodecoverage($codecoverage) + { + $this->codecoverage = $codecoverage; + } + + public function setProcessIsolation($processIsolation) + { + $this->processIsolation = $processIsolation; + } + + public function setUseCustomErrorHandler($usecustomerrorhandler) + { + $this->usecustomerrorhandler = $usecustomerrorhandler; + } + + public function setGroups($groups) + { + $token = ' ,;'; + $this->groups = array(); + $tok = strtok($groups, $token); + while ($tok !== false) { + $this->groups[] = $tok; + $tok = strtok($token); + } + } + + public function setExcludeGroups($excludeGroups) + { + $token = ' ,;'; + $this->excludeGroups = array(); + $tok = strtok($excludeGroups, $token); + while ($tok !== false) { + $this->excludeGroups[] = $tok; + $tok = strtok($token); + } + } + + /** + * Add a new formatter to all tests of this task. + * + * @param FormatterElement formatter element + */ + public function addFormatter(FormatterElement $fe) + { + $fe->setParent($this); + $this->formatters[] = $fe; + } + + /** + * The main entry point + * + * @throws BuildException + */ + public function main() + { + if ($this->codecoverage && !extension_loaded('xdebug')) + { + throw new Exception("PHPUnitTask depends on Xdebug being installed to gather code coverage information."); + } + + if ($this->printsummary) + { + $fe = new FormatterElement(); + $fe->setParent($this); + $fe->setType("summary"); + $fe->setUseFile(false); + $this->formatters[] = $fe; + } + + $autoloadSave = spl_autoload_functions(); + + if ($this->bootstrap) + { + require_once $this->bootstrap; + } + + $suite = new PHPUnit_Framework_TestSuite('AllTests'); + + foreach ($this->batchtests as $batchtest) + { + $batchtest->addToTestSuite($suite); + } + + $this->execute($suite); + + if ($this->testfailed) + { + throw new BuildException($this->testfailuremessage); + } + + $autoloadNew = spl_autoload_functions(); + foreach ($autoloadNew as $autoload) { + spl_autoload_unregister($autoload); + } + + foreach ($autoloadSave as $autoload) { + spl_autoload_register($autoload); + } + } + + /** + * @throws BuildException + */ + protected function execute($suite) + { + $runner = new PHPUnitTestRunner($this->project, $this->groups, $this->excludeGroups, $this->processIsolation); + + if ($this->codecoverage) { + /** + * Add some defaults to the PHPUnit filter + */ + $pwd = dirname(__FILE__); + $path = realpath($pwd . '/../../../'); + + $filter = new PHP_CodeCoverage_Filter(); + $filter->addDirectoryToBlacklist($path); + $runner->setCodecoverage(new PHP_CodeCoverage(null, $filter)); + } + + $runner->setUseCustomErrorHandler($this->usecustomerrorhandler); + + foreach ($this->formatters as $fe) + { + $formatter = $fe->getFormatter(); + + if ($fe->getUseFile()) + { + $destFile = new PhingFile($fe->getToDir(), $fe->getOutfile()); + + $writer = new FileWriter($destFile->getAbsolutePath()); + + $formatter->setOutput($writer); + } + else + { + $formatter->setOutput($this->getDefaultOutput()); + } + + $runner->addFormatter($formatter); + + $formatter->startTestRun(); + } + + $runner->run($suite); + + foreach ($this->formatters as $fe) + { + $formatter = $fe->getFormatter(); + $formatter->endTestRun(); + } + + $retcode = $runner->getRetCode(); + + if ($retcode == PHPUnitTestRunner::ERRORS) { + if ($this->errorproperty) { + $this->project->setNewProperty($this->errorproperty, true); + } + if ($this->haltonerror) { + $this->testfailed = true; + $this->testfailuremessage = $runner->getLastErrorMessage(); + } + } elseif ($retcode == PHPUnitTestRunner::FAILURES) { + if ($this->failureproperty) { + $this->project->setNewProperty($this->failureproperty, true); + } + + if ($this->haltonfailure) { + $this->testfailed = true; + $this->testfailuremessage = $runner->getLastFailureMessage(); + } + } elseif ($retcode == PHPUnitTestRunner::INCOMPLETES) { + if ($this->incompleteproperty) { + $this->project->setNewProperty($this->incompleteproperty, true); + } + + if ($this->haltonincomplete) { + $this->testfailed = true; + $this->testfailuremessage = $runner->getLastIncompleteMessage(); + } + } elseif ($retcode == PHPUnitTestRunner::SKIPPED) { + if ($this->skippedproperty) { + $this->project->setNewProperty($this->skippedproperty, true); + } + + if ($this->haltonskipped) { + $this->testfailed = true; + $this->testfailuremessage = $runner->getLastSkippedMessage(); + } + } + } + + protected function getDefaultOutput() + { + return new LogWriter($this); + } + + /** + * Adds a set of tests based on pattern matching. + * + * @return BatchTest a new instance of a batch test. + */ + public function createBatchTest() + { + $batchtest = new BatchTest($this->getProject()); + + $this->batchtests[] = $batchtest; + + return $batchtest; + } +} + |