Changeset View
Changeset View
Standalone View
Standalone View
src/unit/engine/CSharpToolsTestEngine.php
| <?php | <?php | ||||
| /** | /** | ||||
| * Uses cscover (http://github.com/hach-que/cstools) to report code coverage. | * Uses cscover (http://github.com/hach-que/cstools) to report code coverage. | ||||
| * | * | ||||
| * This engine inherits from `XUnitTestEngine`, where xUnit is used to actually | * This engine inherits from `XUnitTestEngine`, where xUnit is used to actually | ||||
| * run the unit tests and this class provides a thin layer on top to collect | * run the unit tests and this class provides a thin layer on top to collect | ||||
| * code coverage data with a third-party tool. | * code coverage data with a third-party tool. | ||||
| * | |||||
| * @group unitrun | |||||
| */ | */ | ||||
| final class CSharpToolsTestEngine extends XUnitTestEngine { | final class CSharpToolsTestEngine extends XUnitTestEngine { | ||||
| private $cscoverHintPath; | private $cscoverHintPath; | ||||
| private $coverEngine; | private $coverEngine; | ||||
| private $cachedResults; | private $cachedResults; | ||||
| private $matchRegex; | private $matchRegex; | ||||
| private $excludedFiles; | private $excludedFiles; | ||||
| /** | /** | ||||
| * Overridden version of `loadEnvironment` to support a different set | * Overridden version of `loadEnvironment` to support a different set of | ||||
| * of configuration values and to pull in the cstools config for | * configuration values and to pull in the cstools config for code coverage. | ||||
| * code coverage. | |||||
| */ | */ | ||||
| protected function loadEnvironment() { | protected function loadEnvironment() { | ||||
| $config = $this->getConfigurationManager(); | $config = $this->getConfigurationManager(); | ||||
| $this->cscoverHintPath = | $this->cscoverHintPath = $config->getConfigFromAnySource( | ||||
| $config->getConfigFromAnySource('unit.csharp.cscover.binary'); | 'unit.csharp.cscover.binary'); | ||||
| $this->matchRegex = | $this->matchRegex = $config->getConfigFromAnySource( | ||||
| $config->getConfigFromAnySource('unit.csharp.coverage.match'); | 'unit.csharp.coverage.match'); | ||||
| $this->excludedFiles = | $this->excludedFiles = $config->getConfigFromAnySource( | ||||
| $config->getConfigFromAnySource('unit.csharp.coverage.excluded'); | 'unit.csharp.coverage.excluded'); | ||||
| parent::loadEnvironment(); | parent::loadEnvironment(); | ||||
| if ($this->getEnableCoverage() === false) { | if ($this->getEnableCoverage() === false) { | ||||
| return; | return; | ||||
| } | } | ||||
| // Determine coverage path. | // Determine coverage path. | ||||
| if ($this->cscoverHintPath === null) { | if ($this->cscoverHintPath === null) { | ||||
| throw new Exception( | throw new Exception( | ||||
| "Unable to locate cscover. Configure it with ". | "Unable to locate cscover. Configure it with ". | ||||
| "the `unit.csharp.coverage.binary' option in .arcconfig"); | "the `unit.csharp.coverage.binary' option in .arcconfig"); | ||||
| } | } | ||||
| $cscover = $this->projectRoot.DIRECTORY_SEPARATOR.$this->cscoverHintPath; | $cscover = $this->projectRoot.DIRECTORY_SEPARATOR.$this->cscoverHintPath; | ||||
| if (file_exists($cscover)) { | if (file_exists($cscover)) { | ||||
| $this->coverEngine = Filesystem::resolvePath($cscover); | $this->coverEngine = Filesystem::resolvePath($cscover); | ||||
| } else { | } else { | ||||
| throw new Exception( | throw new Exception( | ||||
| 'Unable to locate cscover coverage runner '. | 'Unable to locate cscover coverage runner (have you built yet?)'); | ||||
| '(have you built yet?)'); | |||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Returns whether the specified assembly should be instrumented for | * Returns whether the specified assembly should be instrumented for | ||||
| * code coverage reporting. Checks the excluded file list and the | * code coverage reporting. Checks the excluded file list and the | ||||
| * matching regex if they are configured. | * matching regex if they are configured. | ||||
| * | * | ||||
| * @return boolean Whether the assembly should be instrumented. | * @return boolean Whether the assembly should be instrumented. | ||||
| */ | */ | ||||
| private function assemblyShouldBeInstrumented($file) { | private function assemblyShouldBeInstrumented($file) { | ||||
| if ($this->excludedFiles !== null) { | if ($this->excludedFiles !== null) { | ||||
| if (array_key_exists((string)$file, $this->excludedFiles)) { | if (array_key_exists((string)$file, $this->excludedFiles)) { | ||||
| return false; | return false; | ||||
| Show All 18 Lines | final class CSharpToolsTestEngine extends XUnitTestEngine { | ||||
| * stored in an array. | * stored in an array. | ||||
| */ | */ | ||||
| protected function buildTestFuture($test_assembly) { | protected function buildTestFuture($test_assembly) { | ||||
| if ($this->getEnableCoverage() === false) { | if ($this->getEnableCoverage() === false) { | ||||
| return parent::buildTestFuture($test_assembly); | return parent::buildTestFuture($test_assembly); | ||||
| } | } | ||||
| // FIXME: Can't use TempFile here as xUnit doesn't like | // FIXME: Can't use TempFile here as xUnit doesn't like | ||||
| // UNIX-style full paths. It sees the leading / as the | // UNIX-style full paths. It sees the leading / as the | ||||
| // start of an option flag, even when quoted. | // start of an option flag, even when quoted. | ||||
| $xunit_temp = Filesystem::readRandomCharacters(10).'.results.xml'; | $xunit_temp = Filesystem::readRandomCharacters(10).'.results.xml'; | ||||
| if (file_exists($xunit_temp)) { | if (file_exists($xunit_temp)) { | ||||
| unlink($xunit_temp); | unlink($xunit_temp); | ||||
| } | } | ||||
| $cover_temp = new TempFile(); | $cover_temp = new TempFile(); | ||||
| $cover_temp->setPreserveFile(true); | $cover_temp->setPreserveFile(true); | ||||
| $xunit_cmd = $this->runtimeEngine; | $xunit_cmd = $this->runtimeEngine; | ||||
| ▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | final class CSharpToolsTestEngine extends XUnitTestEngine { | ||||
| protected function parseCoverageResult($cover_file) { | protected function parseCoverageResult($cover_file) { | ||||
| if ($this->getEnableCoverage() === false) { | if ($this->getEnableCoverage() === false) { | ||||
| return parent::parseCoverageResult($cover_file); | return parent::parseCoverageResult($cover_file); | ||||
| } | } | ||||
| return $this->readCoverage($cover_file); | return $this->readCoverage($cover_file); | ||||
| } | } | ||||
| /** | /** | ||||
| * Retrieves the cached results for a coverage result file. The coverage | * Retrieves the cached results for a coverage result file. The coverage | ||||
| * result file is XML and can be large depending on what has been instrumented | * result file is XML and can be large depending on what has been instrumented | ||||
| * so we cache it in case it's requested again. | * so we cache it in case it's requested again. | ||||
| * | * | ||||
| * @param string The name of the coverage file. | * @param string The name of the coverage file. | ||||
| * @return array Code coverage results, or null if not cached. | * @return array Code coverage results, or null if not cached. | ||||
| */ | */ | ||||
| private function getCachedResultsIfPossible($cover_file) { | private function getCachedResultsIfPossible($cover_file) { | ||||
| if ($this->cachedResults == null) { | if ($this->cachedResults == null) { | ||||
| Show All 14 Lines | final class CSharpToolsTestEngine extends XUnitTestEngine { | ||||
| private function addCachedResults($cover_file, array $results) { | private function addCachedResults($cover_file, array $results) { | ||||
| if ($this->cachedResults == null) { | if ($this->cachedResults == null) { | ||||
| $this->cachedResults = array(); | $this->cachedResults = array(); | ||||
| } | } | ||||
| $this->cachedResults[(string)$cover_file] = $results; | $this->cachedResults[(string)$cover_file] = $results; | ||||
| } | } | ||||
| /** | /** | ||||
| * Processes a set of XML tags as code coverage results. We parse | * Processes a set of XML tags as code coverage results. We parse | ||||
| * the `instrumented` and `executed` tags with this method so that | * the `instrumented` and `executed` tags with this method so that | ||||
| * we can access the data multiple times without a performance hit. | * we can access the data multiple times without a performance hit. | ||||
| * | * | ||||
| * @param array The array of XML tags to parse. | * @param array The array of XML tags to parse. | ||||
| * @return array A PHP array containing the data. | * @return array A PHP array containing the data. | ||||
| */ | */ | ||||
| private function processTags($tags) { | private function processTags($tags) { | ||||
| $results = array(); | $results = array(); | ||||
| ▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | foreach ($files as $file) { | ||||
| } | } | ||||
| $reports[$file] = implode($coverage); | $reports[$file] = implode($coverage); | ||||
| } | } | ||||
| $this->addCachedResults($cover_file, $reports); | $this->addCachedResults($cover_file, $reports); | ||||
| return $reports; | return $reports; | ||||
| } | } | ||||
| } | } | ||||