Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2892506
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
5 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/unit/engine/NoseTestEngine.php b/src/unit/engine/NoseTestEngine.php
index 039daf5e..a411303d 100644
--- a/src/unit/engine/NoseTestEngine.php
+++ b/src/unit/engine/NoseTestEngine.php
@@ -1,168 +1,177 @@
<?php
/**
* Very basic 'nose' unit test engine wrapper.
*
* Requires nose 1.1.3 for code coverage.
*/
final class NoseTestEngine extends ArcanistUnitTestEngine {
private $parser;
+ protected function supportsRunAllTests() {
+ return true;
+ }
+
public function run() {
+ if ($this->getRunAllTests()) {
+ $root = $this->getWorkingCopy()->getProjectRoot();
+ return $this->runTests(array($root), './');
+ }
+
$paths = $this->getPaths();
$affected_tests = array();
foreach ($paths as $path) {
$absolute_path = Filesystem::resolvePath($path);
if (is_dir($absolute_path)) {
$absolute_test_path = Filesystem::resolvePath('tests/'.$path);
if (is_readable($absolute_test_path)) {
$affected_tests[] = $absolute_test_path;
}
}
if (is_readable($absolute_path)) {
$filename = basename($path);
$directory = dirname($path);
// assumes directory layout: tests/<package>/test_<module>.py
$relative_test_path = 'tests/'.$directory.'/test_'.$filename;
$absolute_test_path = Filesystem::resolvePath($relative_test_path);
if (is_readable($absolute_test_path)) {
$affected_tests[] = $absolute_test_path;
}
}
}
return $this->runTests($affected_tests, './');
}
public function runTests($test_paths, $source_path) {
if (empty($test_paths)) {
return array();
}
$futures = array();
$tmpfiles = array();
foreach ($test_paths as $test_path) {
$xunit_tmp = new TempFile();
$cover_tmp = new TempFile();
$future = $this->buildTestFuture($test_path, $xunit_tmp, $cover_tmp);
$futures[$test_path] = $future;
$tmpfiles[$test_path] = array(
'xunit' => $xunit_tmp,
'cover' => $cover_tmp,
);
}
$results = array();
$futures = id(new FutureIterator($futures))
->limit(4);
foreach ($futures as $test_path => $future) {
try {
list($stdout, $stderr) = $future->resolvex();
} catch (CommandException $exc) {
if ($exc->getError() > 1) {
// 'nose' returns 1 when tests are failing/broken.
throw $exc;
}
}
$xunit_tmp = $tmpfiles[$test_path]['xunit'];
$cover_tmp = $tmpfiles[$test_path]['cover'];
$this->parser = new ArcanistXUnitTestResultParser();
$results[] = $this->parseTestResults(
$source_path,
$xunit_tmp,
$cover_tmp);
}
return array_mergev($results);
}
public function buildTestFuture($path, $xunit_tmp, $cover_tmp) {
$cmd_line = csprintf(
'nosetests --with-xunit --xunit-file=%s',
$xunit_tmp);
if ($this->getEnableCoverage() !== false) {
$cmd_line .= csprintf(
' --with-coverage --cover-xml --cover-xml-file=%s',
$cover_tmp);
}
return new ExecFuture('%C %s', $cmd_line, $path);
}
public function parseTestResults($source_path, $xunit_tmp, $cover_tmp) {
$results = $this->parser->parseTestResults(
Filesystem::readFile($xunit_tmp));
// coverage is for all testcases in the executed $path
if ($this->getEnableCoverage() !== false) {
$coverage = $this->readCoverage($cover_tmp, $source_path);
foreach ($results as $result) {
$result->setCoverage($coverage);
}
}
return $results;
}
public function readCoverage($cover_file, $source_path) {
$coverage_dom = new DOMDocument();
$coverage_dom->loadXML(Filesystem::readFile($cover_file));
$reports = array();
$classes = $coverage_dom->getElementsByTagName('class');
foreach ($classes as $class) {
$path = $class->getAttribute('filename');
$root = $this->getWorkingCopy()->getProjectRoot();
if (!Filesystem::isDescendant($path, $root)) {
continue;
}
// get total line count in file
$line_count = count(phutil_split_lines(Filesystem::readFile($path)));
$coverage = '';
$start_line = 1;
$lines = $class->getElementsByTagName('line');
for ($ii = 0; $ii < $lines->length; $ii++) {
$line = $lines->item($ii);
$next_line = (int)$line->getAttribute('number');
for ($start_line; $start_line < $next_line; $start_line++) {
$coverage .= 'N';
}
if ((int)$line->getAttribute('hits') == 0) {
$coverage .= 'U';
} else if ((int)$line->getAttribute('hits') > 0) {
$coverage .= 'C';
}
$start_line++;
}
if ($start_line < $line_count) {
foreach (range($start_line, $line_count) as $line_num) {
$coverage .= 'N';
}
}
$reports[$path] = $coverage;
}
return $reports;
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 16:55 (2 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1126690
Default Alt Text
(5 KB)
Attached To
Mode
rARC Arcanist
Attached
Detach File
Event Timeline
Log In to Comment