mirror of
https://we.phorge.it/source/arcanist.git
synced 2025-01-22 12:41:18 +01: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:
parent
0bf5c3603c
commit
716ce2482c
4 changed files with 155 additions and 31 deletions
|
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue