1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-09-20 00:49:11 +02:00

Implement --everything, --json and --ugly flags for arc unit

Summary: Adds "arc unit --everything", which runs every available test, provided the test engine supports it. Also add JSON output.

Test Plan: Ran `arc unit --everything` in arcanist/, libphutil/ and phabricator/. Saw all tests run.

Reviewers: btrahan, vrana

Reviewed By: vrana

CC: aran

Maniphest Tasks: T2065

Differential Revision: https://secure.phabricator.com/D4214
This commit is contained in:
epriestley 2012-12-17 12:56:41 -08:00
parent 0bf5c3603c
commit 716ce2482c
4 changed files with 155 additions and 31 deletions

View file

@ -125,4 +125,16 @@ final class ArcanistUnitTestResult {
return $base;
}
public function toDictionary() {
return array(
'name' => $this->getName(),
'link' => $this->getLink(),
'result' => $this->getResult(),
'duration' => $this->getDuration(),
'extra' => $this->getExtraData(),
'userData' => $this->getUserData(),
'coverage' => $this->getCoverage(),
);
}
}

View file

@ -13,6 +13,27 @@ abstract class ArcanistBaseUnitTestEngine {
protected $diffID;
private $enableAsyncTests;
private $enableCoverage;
private $runAllTests;
public function setRunAllTests($run_all_tests) {
if (!$this->supportsRunAllTests() && $run_all_tests) {
$class = get_class($this);
throw new Exception(
"Engine '{$class}' does not support --everything.");
}
$this->runAllTests = $run_all_tests;
return $this;
}
public function getRunAllTests() {
return $this->runAllTests;
}
protected function supportsRunAllTests() {
return false;
}
final public function __construct() {

View file

@ -7,9 +7,86 @@
*/
final class PhutilUnitTestEngine extends ArcanistBaseUnitTestEngine {
public function run() {
protected function supportsRunAllTests() {
return true;
}
$bootloader = PhutilBootloader::getInstance();
public function run() {
if ($this->getRunAllTests()) {
$run_tests = $this->getAllTests();
} else {
$run_tests = $this->getTestsForPaths();
}
if (!$run_tests) {
throw new ArcanistNoEffectException("No tests to run.");
}
$enable_coverage = $this->getEnableCoverage();
if ($enable_coverage !== false) {
if (!function_exists('xdebug_start_code_coverage')) {
if ($enable_coverage === true) {
throw new ArcanistUsageException(
"You specified --coverage but xdebug is not available, so ".
"coverage can not be enabled for PhutilUnitTestEngine.");
}
} else {
$enable_coverage = true;
}
}
$project_root = $this->getWorkingCopy()->getProjectRoot();
$results = array();
foreach ($run_tests as $test_class) {
$test_case = newv($test_class, array());
$test_case->setEnableCoverage($enable_coverage);
$test_case->setProjectRoot($project_root);
if ($this->getPaths()) {
$test_case->setPaths($this->getPaths());
}
$results[] = $test_case->run();
}
$results = array_mergev($results);
return $results;
}
private function getAllTests() {
$project_root = $this->getWorkingCopy()->getProjectRoot();
$symbols = id(new PhutilSymbolLoader())
->setType('class')
->setAncestorClass('ArcanistPhutilTestCase')
->setConcreteOnly(true)
->selectSymbolsWithoutLoading();
$in_working_copy = array();
$run_tests = array();
foreach ($symbols as $symbol) {
if (!preg_match('@/__tests__/@', $symbol['where'])) {
continue;
}
$library = $symbol['library'];
if (!isset($in_working_copy[$library])) {
$library_root = phutil_get_library_root($library);
$in_working_copy[$library] = Filesystem::isDescendant(
$library_root,
$project_root);
}
if ($in_working_copy[$library]) {
$run_tests[] = $symbol['name'];
}
}
return $run_tests;
}
private function getTestsForPaths() {
$project_root = $this->getWorkingCopy()->getProjectRoot();
$look_here = array();
@ -89,34 +166,7 @@ final class PhutilUnitTestEngine extends ArcanistBaseUnitTestEngine {
}
$run_tests = array_keys($run_tests);
if (!$run_tests) {
throw new ArcanistNoEffectException("No tests to run.");
}
$enable_coverage = $this->getEnableCoverage();
if ($enable_coverage !== false) {
if (!function_exists('xdebug_start_code_coverage')) {
if ($enable_coverage === true) {
throw new ArcanistUsageException(
"You specified --coverage but xdebug is not available, so ".
"coverage can not be enabled for PhutilUnitTestEngine.");
}
} else {
$enable_coverage = true;
}
}
$results = array();
foreach ($run_tests as $test_class) {
$test_case = newv($test_class, array());
$test_case->setEnableCoverage($enable_coverage);
$test_case->setProjectRoot($project_root);
$test_case->setPaths($this->getPaths());
$results[] = $test_case->run();
}
$results = array_mergev($results);
return $results;
return $run_tests;
}
}

View file

@ -69,6 +69,18 @@ EOTEXT
'help' => "Show a detailed coverage report on the CLI. Implies ".
"--coverage.",
),
'json' => array(
'help' => 'Report results in JSON format.',
),
'everything' => array(
'help' => 'Run every test.',
'conflicts' => array(
'rev' => '--everything runs all tests.',
),
),
'ugly' => array(
'help' => 'With --json, use uglier (but more efficient) formatting.',
),
'*' => 'paths',
);
}
@ -101,6 +113,12 @@ EOTEXT
$paths = $this->getArgument('paths');
$rev = $this->getArgument('rev');
$everything = $this->getArgument('everything');
if ($everything && $paths) {
throw new ArcanistUsageException(
"You can not specify paths with --everything. The --everything ".
"flag runs every test.");
}
$paths = $this->selectPathsForWorkflow($paths, $rev);
@ -113,7 +131,11 @@ EOTEXT
$this->engine = newv($engine_class, array());
$this->engine->setWorkingCopy($working_copy);
$this->engine->setPaths($paths);
if ($everything) {
$this->engine->setRunAllTests(true);
} else {
$this->engine->setPaths($paths);
}
$this->engine->setArguments($this->getPassthruArgumentsAsMap('unit'));
$enable_coverage = null; // Means "default".
@ -137,6 +159,12 @@ EOTEXT
$console = PhutilConsole::getConsole();
$json_output = $this->getArgument('json');
if ($json_output) {
$console->disableOut();
}
$unresolved = array();
$coverage = array();
$postponed_count = 0;
@ -234,6 +262,19 @@ EOTEXT
}
}
if ($json_output) {
$console->enableOut();
$data = array_values(mpull($results, 'toDictionary'));
if ($this->getArgument('ugly')) {
$console->writeOut('%s', json_encode($data));
} else {
$json = new PhutilJSON();
$console->writeOut('%s', $json->encodeFormatted($data));
}
}
return $overall_result;
}