mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-26 15:30:58 +01:00
Show coverage information in Differential
Summary: Render coverage information in the right gutter, if available. We could render some kind of summary report deal too but this seems like a good start. Test Plan: - Looked at diffs with coverage. - Looked at diffs without coverage. - Used inline comments, diff-of-diff, "show more", "show entire file", "show generated file", "undo". Nothing seemed disrupted by the addition of a 5th column. Reviewers: btrahan, tuomaspelkonen, jungejason Reviewed By: btrahan CC: zeeg, aran, epriestley Maniphest Tasks: T140 Differential Revision: https://secure.phabricator.com/D1527
This commit is contained in:
parent
3d7a1d936c
commit
1e9492f8c2
6 changed files with 175 additions and 43 deletions
|
@ -163,7 +163,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'differential-changeset-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/bc78a228/rsrc/css/application/differential/changeset-view.css',
|
||||
'uri' => '/res/2b0c9b6a/rsrc/css/application/differential/changeset-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -213,7 +213,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'differential-revision-comment-css' =>
|
||||
array(
|
||||
'uri' => '/res/76b6d378/rsrc/css/application/differential/revision-comment.css',
|
||||
'uri' => '/res/be9a95b4/rsrc/css/application/differential/revision-comment.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -332,13 +332,14 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
0 =>
|
||||
array(
|
||||
'uri' => '/res/14c48a9f/rsrc/js/javelin/lib/__tests__/behavior.js',
|
||||
'uri' => '/res/b6096fdd/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-behavior',
|
||||
0 => 'javelin-uri',
|
||||
1 => 'javelin-php-serializer',
|
||||
),
|
||||
'disk' => '/rsrc/js/javelin/lib/__tests__/behavior.js',
|
||||
'disk' => '/rsrc/js/javelin/lib/__tests__/URI.js',
|
||||
),
|
||||
'javelin-behavior-aphront-basic-tokenizer' =>
|
||||
array(
|
||||
|
@ -1762,6 +1763,27 @@ celerity_register_resource_map(array(
|
|||
'uri' => '/res/pkg/540effd7/typeahead.pkg.js',
|
||||
'type' => 'js',
|
||||
),
|
||||
'80580cea' =>
|
||||
array(
|
||||
'name' => 'differential.pkg.css',
|
||||
'symbols' =>
|
||||
array(
|
||||
0 => 'differential-core-view-css',
|
||||
1 => 'differential-changeset-view-css',
|
||||
2 => 'differential-revision-detail-css',
|
||||
3 => 'differential-revision-history-css',
|
||||
4 => 'differential-table-of-contents-css',
|
||||
5 => 'differential-revision-comment-css',
|
||||
6 => 'differential-revision-add-comment-css',
|
||||
7 => 'differential-revision-comment-list-css',
|
||||
8 => 'phabricator-object-selector-css',
|
||||
9 => 'aphront-headsup-action-list-view-css',
|
||||
10 => 'phabricator-content-source-view-css',
|
||||
11 => 'differential-local-commits-view-css',
|
||||
),
|
||||
'uri' => '/res/pkg/80580cea/differential.pkg.css',
|
||||
'type' => 'css',
|
||||
),
|
||||
'a6562582' =>
|
||||
array(
|
||||
'name' => 'differential.pkg.js',
|
||||
|
@ -1786,27 +1808,6 @@ celerity_register_resource_map(array(
|
|||
'uri' => '/res/pkg/a6562582/differential.pkg.js',
|
||||
'type' => 'js',
|
||||
),
|
||||
'ab397f85' =>
|
||||
array(
|
||||
'name' => 'differential.pkg.css',
|
||||
'symbols' =>
|
||||
array(
|
||||
0 => 'differential-core-view-css',
|
||||
1 => 'differential-changeset-view-css',
|
||||
2 => 'differential-revision-detail-css',
|
||||
3 => 'differential-revision-history-css',
|
||||
4 => 'differential-table-of-contents-css',
|
||||
5 => 'differential-revision-comment-css',
|
||||
6 => 'differential-revision-add-comment-css',
|
||||
7 => 'differential-revision-comment-list-css',
|
||||
8 => 'phabricator-object-selector-css',
|
||||
9 => 'aphront-headsup-action-list-view-css',
|
||||
10 => 'phabricator-content-source-view-css',
|
||||
11 => 'differential-local-commits-view-css',
|
||||
),
|
||||
'uri' => '/res/pkg/ab397f85/differential.pkg.css',
|
||||
'type' => 'css',
|
||||
),
|
||||
'b164acea' =>
|
||||
array(
|
||||
'name' => 'javelin.pkg.js',
|
||||
|
@ -1856,23 +1857,23 @@ celerity_register_resource_map(array(
|
|||
'aphront-crumbs-view-css' => '16378540',
|
||||
'aphront-dialog-view-css' => '16378540',
|
||||
'aphront-form-view-css' => '16378540',
|
||||
'aphront-headsup-action-list-view-css' => 'ab397f85',
|
||||
'aphront-headsup-action-list-view-css' => '80580cea',
|
||||
'aphront-list-filter-view-css' => '16378540',
|
||||
'aphront-panel-view-css' => '16378540',
|
||||
'aphront-side-nav-view-css' => '16378540',
|
||||
'aphront-table-view-css' => '16378540',
|
||||
'aphront-tokenizer-control-css' => '16378540',
|
||||
'aphront-typeahead-control-css' => '16378540',
|
||||
'differential-changeset-view-css' => 'ab397f85',
|
||||
'differential-core-view-css' => 'ab397f85',
|
||||
'differential-changeset-view-css' => '80580cea',
|
||||
'differential-core-view-css' => '80580cea',
|
||||
'differential-inline-comment-editor' => 'a6562582',
|
||||
'differential-local-commits-view-css' => 'ab397f85',
|
||||
'differential-revision-add-comment-css' => 'ab397f85',
|
||||
'differential-revision-comment-css' => 'ab397f85',
|
||||
'differential-revision-comment-list-css' => 'ab397f85',
|
||||
'differential-revision-detail-css' => 'ab397f85',
|
||||
'differential-revision-history-css' => 'ab397f85',
|
||||
'differential-table-of-contents-css' => 'ab397f85',
|
||||
'differential-local-commits-view-css' => '80580cea',
|
||||
'differential-revision-add-comment-css' => '80580cea',
|
||||
'differential-revision-comment-css' => '80580cea',
|
||||
'differential-revision-comment-list-css' => '80580cea',
|
||||
'differential-revision-detail-css' => '80580cea',
|
||||
'differential-revision-history-css' => '80580cea',
|
||||
'differential-table-of-contents-css' => '80580cea',
|
||||
'diffusion-commit-view-css' => '03ef179e',
|
||||
'javelin-behavior' => 'b164acea',
|
||||
'javelin-behavior-aphront-basic-tokenizer' => '540effd7',
|
||||
|
@ -1910,14 +1911,14 @@ celerity_register_resource_map(array(
|
|||
'javelin-util' => 'b164acea',
|
||||
'javelin-vector' => 'b164acea',
|
||||
'javelin-workflow' => '46547a92',
|
||||
'phabricator-content-source-view-css' => 'ab397f85',
|
||||
'phabricator-content-source-view-css' => '80580cea',
|
||||
'phabricator-core-buttons-css' => '16378540',
|
||||
'phabricator-core-css' => '16378540',
|
||||
'phabricator-directory-css' => '16378540',
|
||||
'phabricator-drag-and-drop-file-upload' => 'a6562582',
|
||||
'phabricator-keyboard-shortcut' => '46547a92',
|
||||
'phabricator-keyboard-shortcut-manager' => '46547a92',
|
||||
'phabricator-object-selector-css' => 'ab397f85',
|
||||
'phabricator-object-selector-css' => '80580cea',
|
||||
'phabricator-remarkup-css' => '16378540',
|
||||
'phabricator-shaped-request' => 'a6562582',
|
||||
'phabricator-standard-page-view' => '16378540',
|
||||
|
|
|
@ -125,11 +125,37 @@ class DifferentialChangesetViewController extends DifferentialController {
|
|||
$changeset = $choice;
|
||||
}
|
||||
|
||||
$coverage = null;
|
||||
if ($right->getDiffID()) {
|
||||
$unit = id(new DifferentialDiffProperty())->loadOneWhere(
|
||||
'diffID = %d AND name = %s',
|
||||
$right->getDiffID(),
|
||||
'arc:unit');
|
||||
|
||||
if ($unit) {
|
||||
$coverage = array();
|
||||
foreach ($unit->getData() as $result) {
|
||||
$result_coverage = idx($result, 'coverage');
|
||||
if (!$result_coverage) {
|
||||
continue;
|
||||
}
|
||||
$file_coverage = idx($result_coverage, $right->getFileName());
|
||||
if (!$file_coverage) {
|
||||
continue;
|
||||
}
|
||||
$coverage[] = $file_coverage;
|
||||
}
|
||||
|
||||
$coverage = ArcanistUnitTestResult::mergeCoverage($coverage);
|
||||
}
|
||||
}
|
||||
|
||||
$spec = $request->getStr('range');
|
||||
list($range_s, $range_e, $mask) =
|
||||
DifferentialChangesetParser::parseRangeSpecification($spec);
|
||||
|
||||
$parser = new DifferentialChangesetParser();
|
||||
$parser->setCoverage($coverage);
|
||||
$parser->setChangeset($changeset);
|
||||
$parser->setRenderingReference($rendering_reference);
|
||||
$parser->setRenderCacheKey($render_cache_key);
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('arcanist', 'unit/result');
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/400');
|
||||
phutil_require_module('phabricator', 'aphront/response/404');
|
||||
phutil_require_module('phabricator', 'aphront/response/ajax');
|
||||
|
|
|
@ -53,6 +53,7 @@ class DifferentialChangesetParser {
|
|||
|
||||
private $lineWidth = 80;
|
||||
private $isTopLevel;
|
||||
private $coverage;
|
||||
|
||||
const CACHE_VERSION = 4;
|
||||
|
||||
|
@ -177,6 +178,11 @@ class DifferentialChangesetParser {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setCoverage($coverage) {
|
||||
$this->coverage = $coverage;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function parseHunk(DifferentialHunk $hunk) {
|
||||
$lines = $hunk->getChanges();
|
||||
|
||||
|
@ -1120,7 +1126,7 @@ class DifferentialChangesetParser {
|
|||
array(
|
||||
'sigil' => 'context-target',
|
||||
),
|
||||
'<td class="differential-shield" colspan="4">'.
|
||||
'<td class="differential-shield" colspan="5">'.
|
||||
phutil_escape_html($message).
|
||||
$more.
|
||||
'</td>');
|
||||
|
@ -1141,7 +1147,7 @@ class DifferentialChangesetParser {
|
|||
array(
|
||||
'sigil' => 'context-target',
|
||||
),
|
||||
'<td colspan="4" class="show-more">'.
|
||||
'<td colspan="5" class="show-more">'.
|
||||
'Context not available.'.
|
||||
'</td>');
|
||||
}
|
||||
|
@ -1293,7 +1299,7 @@ class DifferentialChangesetParser {
|
|||
array(
|
||||
'sigil' => 'context-target',
|
||||
),
|
||||
'<td colspan="4" class="show-more">'.
|
||||
'<td colspan="5" class="show-more">'.
|
||||
implode(' • ', $contents).
|
||||
'</td>');
|
||||
|
||||
|
@ -1320,10 +1326,24 @@ class DifferentialChangesetParser {
|
|||
$o_attr = null;
|
||||
}
|
||||
|
||||
|
||||
if (isset($this->new[$ii])) {
|
||||
$n_num = $this->new[$ii]['line'];
|
||||
$n_text = isset($this->newRender[$ii]) ? $this->newRender[$ii] : null;
|
||||
$n_attr = null;
|
||||
|
||||
$cov_class = null;
|
||||
if ($this->coverage !== null) {
|
||||
if (empty($this->coverage[$n_num - 1])) {
|
||||
$cov_class = 'N';
|
||||
} else {
|
||||
$cov_class = $this->coverage[$n_num - 1];
|
||||
}
|
||||
$cov_class = 'cov-'.$cov_class;
|
||||
}
|
||||
|
||||
$n_cov = '<td class="cov '.$cov_class.'"></td>';
|
||||
|
||||
if ($this->new[$ii]['type']) {
|
||||
if (empty($this->old[$ii])) {
|
||||
$n_attr = ' class="new new-full"';
|
||||
|
@ -1335,6 +1355,7 @@ class DifferentialChangesetParser {
|
|||
$n_num = null;
|
||||
$n_text = null;
|
||||
$n_attr = null;
|
||||
$n_cov = null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1363,6 +1384,7 @@ class DifferentialChangesetParser {
|
|||
'<td'.$o_attr.'>'.$o_text.'</td>'.
|
||||
'<th'.$n_id.'>'.$n_num.'</th>'.
|
||||
'<td'.$n_attr.'>'.$n_text.'</td>'.
|
||||
$n_cov.
|
||||
'</tr>';
|
||||
|
||||
if ($context_not_available && ($ii == $rows - 1)) {
|
||||
|
@ -1375,7 +1397,7 @@ class DifferentialChangesetParser {
|
|||
$html[] =
|
||||
'<tr class="inline"><th /><td>'.
|
||||
$xhp.
|
||||
'</td><th /><td /></tr>';
|
||||
'</td><th /><td /><td /></tr>';
|
||||
}
|
||||
}
|
||||
if ($n_num && isset($new_comments[$n_num])) {
|
||||
|
@ -1384,7 +1406,7 @@ class DifferentialChangesetParser {
|
|||
$html[] =
|
||||
'<tr class="inline"><th /><td /><th /><td>'.
|
||||
$xhp.
|
||||
'</td></tr>';
|
||||
'</td><td /></tr>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
60
src/docs/userguide/arcanist_coverage.diviner
Normal file
60
src/docs/userguide/arcanist_coverage.diviner
Normal file
|
@ -0,0 +1,60 @@
|
|||
@title Arcanist User Guide: Code Coverage
|
||||
@group userguide
|
||||
|
||||
Explains code coverage features in Arcanist and Phabricator.
|
||||
|
||||
= Using Coverage Features =
|
||||
|
||||
If your project has unit tests with coverage integration (see below for
|
||||
instructions on setting it up), you can use "arc" to show coverage reports.
|
||||
|
||||
For example:
|
||||
|
||||
arc unit --detailed-coverage src/some/file.php
|
||||
|
||||
Depending on how your test engine is configured, this will run tests relevant
|
||||
to ##src/some/file.php## and give you a detailed coverage report.
|
||||
|
||||
If the test engine enables coverage by default, it will be uploaded to
|
||||
Differential and displayed in the right gutter when viewing diffs.
|
||||
|
||||
= Enabling Coverage for libphutil, Arcanist and Phabricator =
|
||||
|
||||
If you're contributing, libphutil, Arcanist and Phabricator support coverage if
|
||||
you install Xdebug:
|
||||
|
||||
http://xdebug.org/
|
||||
|
||||
It should be sufficient to correctly install Xdebug; coverage information will
|
||||
be automatically enabled.
|
||||
|
||||
= Building Coverage Support =
|
||||
|
||||
To add coverage support to a unit test engine, just call ##setCoverage()## when
|
||||
building @{class@arcanist:ArcanistUnitTestResult} objects. Provide a map of
|
||||
file names (relative to the working copy root) to coverage report strings.
|
||||
Coverage report strings look like this:
|
||||
|
||||
NNNNNCCCNNNNNNNNCCCCCCNNNUUUNNNNN
|
||||
|
||||
Each line in the file is represented by a character. Valid characters are:
|
||||
|
||||
- **N** Not executable. This is a comment or whitespace which should be
|
||||
ignored when computing test coverage.
|
||||
- **C** Covered. This line has test coverage.
|
||||
- **U** Uncovered. This line is executable but has no test coverage.
|
||||
- **X** Unreachable. If your coverage analysis can detect unreachable code,
|
||||
you can report it here.
|
||||
|
||||
This format is intended to be as simple as possible. A valid coverage result
|
||||
might look like this:
|
||||
|
||||
array(
|
||||
'src/example.php' => 'NNCNNNCNUNNNUNUNUNUNUNC',
|
||||
'src/other.php' => 'NNUNNNUNCNNNUNUNCNCNCNU',
|
||||
);
|
||||
|
||||
You may also want to filter coverage information to the paths passed to the
|
||||
unit test engine. See @{class@arcanist:ArcanistPhutilTestCase} and
|
||||
@{class@arcanist:PhutilUnitTestEngine} for an example of coverage integration
|
||||
in PHP using Xdebug.
|
|
@ -75,6 +75,27 @@
|
|||
background: #aaffaa;
|
||||
}
|
||||
|
||||
.differential-diff td.cov {
|
||||
width: 12px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
td.cov-U {
|
||||
background: #dd3300;
|
||||
}
|
||||
|
||||
td.cov-C {
|
||||
background: #0066ff;
|
||||
}
|
||||
|
||||
td.cov-N {
|
||||
background: #ddeeff;
|
||||
}
|
||||
|
||||
td.cov-X {
|
||||
background: #aa00aa;
|
||||
}
|
||||
|
||||
.differential-diff td.show-more,
|
||||
.differential-diff td.differential-shield {
|
||||
background: #ffffee;
|
||||
|
|
Loading…
Reference in a new issue