浏览代码

SONAR-4094 On each source file, provide the ability to list all unit tests covering at least one line of code in this source file

tags/3.5
Julien Lancelot 11 年前
父节点
当前提交
5e35883be2

+ 3
- 1
plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties 查看文件

@@ -1131,7 +1131,9 @@ overall_coverage_viewer.by=by all tests
coverage_viewer.unit_tests=Unit Tests
coverage_viewer.integration_tests=Integration Tests
coverage_viewer.overall_tests=All Tests
lines_covered_per_test=Lines covered per test
coverage_viewer.per_test=Per test
coverage_viewer.lines_covered_per_test=Lines covered
coverage_viewer.select_test=Select a test


#------------------------------------------------------------------------------

+ 0
- 1
sonar-core/src/main/java/org/sonar/core/test/DefaultTestCase.java 查看文件

@@ -132,5 +132,4 @@ public class DefaultTestCase extends BeanVertex implements MutableTestCase {
}, null);
}


}

+ 10
- 0
sonar-core/src/main/java/org/sonar/core/test/DefaultTestable.java 查看文件

@@ -27,6 +27,7 @@ import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
import org.sonar.api.component.Component;
import org.sonar.api.test.Cover;
import org.sonar.api.test.MutableTestable;
import org.sonar.api.test.TestCase;
import org.sonar.core.component.ComponentVertex;
@@ -62,6 +63,7 @@ public class DefaultTestable extends BeanVertex implements MutableTestable {

public int countTestCasesOfLine(int line) {
int number = 0;
// element().query()
// TODO filter on edge
for (Edge edge : covers()) {
if (Iterables.contains(lines(edge), line)) {
@@ -91,6 +93,14 @@ public class DefaultTestable extends BeanVertex implements MutableTestable {
return coveredLines.build();
}

public Cover coverOfTestCase(final TestCase testCase) {
return Iterables.find(getEdges(DefaultCover.class, Direction.IN, "covers"), new Predicate<Cover>() {
public boolean apply(Cover input) {
return input.testCase().key().equals(testCase.key());
}
}, null);
}

private Iterable<Edge> covers() {
return element().getEdges(Direction.IN, "covers");
}

+ 25
- 0
sonar-core/src/test/java/org/sonar/core/test/DefaultTestableTest.java 查看文件

@@ -21,7 +21,10 @@ package org.sonar.core.test;

import com.google.common.collect.Iterables;
import org.junit.Test;
import org.sonar.api.component.mock.MockSourceFile;
import org.sonar.api.test.MutableTestCase;
import org.sonar.core.component.ComponentVertex;
import org.sonar.core.component.ScanGraph;
import org.sonar.core.graph.BeanGraph;

import java.util.Arrays;
@@ -87,4 +90,26 @@ public class DefaultTestableTest {
assertThat(testable.testCaseByKey("T2")).isEqualTo(testCase2);
assertThat(testable.testCaseByKey("Unknown")).isNull();
}

@Test
public void should_return_cover_of_testCase(){
BeanGraph beanGraph = BeanGraph.createInMemory();

ScanGraph graph = ScanGraph.create();
ComponentVertex file1 = graph.addComponent(MockSourceFile.createMain("org.foo.Bar"));
DefaultTestable testable1 = beanGraph.createAdjacentVertex(file1, DefaultTestable.class, "testable");

ComponentVertex file2 = graph.addComponent(MockSourceFile.createMain("org.foo.File"));
DefaultTestable testable2 = beanGraph.createAdjacentVertex(file2, DefaultTestable.class, "testable");

DefaultTestPlan plan = beanGraph.createVertex(DefaultTestPlan.class);
plan.addTestCase("T1");

MutableTestCase testCase = Iterables.get(plan.testCases(), 0);
testCase.setCover(testable1, Arrays.asList(10, 11, 12));

assertThat(testable1.coverOfTestCase(testCase).testCase()).isEqualTo(testCase);
assertThat(testable1.coverOfTestCase(testCase).testable()).isEqualTo(testable1);
assertThat(testable2.coverOfTestCase(testCase)).isNull();
}
}

+ 2
- 0
sonar-plugin-api/src/main/java/org/sonar/api/test/Testable.java 查看文件

@@ -36,4 +36,6 @@ public interface Testable extends Perspective {

SortedSet<Integer> testedLines();

Cover coverOfTestCase(TestCase testCase);

}

+ 16
- 10
sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb 查看文件

@@ -181,7 +181,9 @@ class ResourceController < ApplicationController
@expandable = (@lines!=nil)
if @lines
metric = Metric.by_key(params[:coverage_filter]||params[:metric])
@coverage_filter = (metric ? metric.key : 'coverage')
@coverage_filter = params[:coverage_filter] if params[:coverage_filter] == 'lines_covered_per_test'
@coverage_filter = (metric ? metric.key : 'coverage') unless @coverage_filter
@test_case_filter = params[:test_case_filter] if !params[:test_case_filter].blank?

it_prefix = ''
it_prefix = 'it_' if (@coverage_filter.start_with?('it_') || @coverage_filter.start_with?('new_it_'))
@@ -195,8 +197,8 @@ class ResourceController < ApplicationController
@hits_by_line.each_pair do |line_id, hits|
line = @lines[line_id-1]
if line
line.covered_lines = 0
line.covered_lines = @testable.countTestCasesOfLine(line_id) if @testable
line.index = line_id
line.covered_lines = @testable ? @testable.countTestCasesOfLine(line_id) : 0
line.hits = hits.to_i
line.conditions = @conditions_by_line[line_id].to_i
line.covered_conditions = @covered_conditions_by_line[line_id].to_i
@@ -216,6 +218,7 @@ class ResourceController < ApplicationController

to = (@period && @snapshot.period_datetime(@period) ? Java::JavaUtil::Date.new(@snapshot.period_datetime(@period).to_f * 1000) : nil)
@filtered = true

if ('lines_to_cover'==@coverage_filter || 'coverage'==@coverage_filter || 'line_coverage'==@coverage_filter ||
'new_lines_to_cover'==@coverage_filter || 'new_coverage'==@coverage_filter || 'new_line_coverage'==@coverage_filter ||
'it_lines_to_cover'==@coverage_filter || 'it_coverage'==@coverage_filter || 'it_line_coverage'==@coverage_filter ||
@@ -245,13 +248,16 @@ class ResourceController < ApplicationController
'overall_uncovered_conditions'==@coverage_filter || 'new_overall_uncovered_conditions' == @coverage_filter)
@coverage_filter="#{it_prefix}uncovered_conditions"
filter_lines { |line| line.conditions && line.covered_conditions && line.covered_conditions<line.conditions && line.after(to) }
end
end

@test_case_filter = params[:test_case_filter]
if @test_case_filter && @testable
#lines = @testable.coverOfTestable(@testable.testCaseByKey(@test_case_filter)).lines
#filter_lines { |line| lines.include? line }
elsif @coverage_filter == 'lines_covered_per_test'
if @test_case_filter
test_case = @testable.testCaseByKey(@test_case_filter)
lines = @testable.coverOfTestCase(test_case).lines
filter_lines { |line| lines.include? line.index }
else
filter_lines { |line| line.covered_lines && line.after(to) }
end
end
end

render :action => 'index', :layout => !request.xhr?
@@ -440,7 +446,7 @@ class ResourceController < ApplicationController
end

class Line
attr_accessor :source, :revision, :author, :datetime, :violations, :hits, :conditions, :covered_conditions, :hidden, :highlighted, :deprecated_conditions_label, :covered_lines
attr_accessor :index, :source, :revision, :author, :datetime, :violations, :hits, :conditions, :covered_conditions, :hidden, :highlighted, :deprecated_conditions_label, :covered_lines

def initialize(source)
@source=source

+ 7
- 2
sonar-server/src/main/webapp/WEB-INF/app/views/resource/_options.html.erb 查看文件

@@ -89,13 +89,18 @@
<option value="overall_uncovered_conditions" <%= 'selected' if @coverage_filter=='overall_uncovered_conditions' -%>><%= Metric.name_for('overall_uncovered_conditions') -%></option>
</optgroup>
<% end %>
<% if @testable && !@testable.testCases.empty? %>
<optgroup label="<%= h message('coverage_viewer.per_test') -%>">
<option value="lines_covered_per_test" <%= 'selected' if @coverage_filter=='lines_covered_per_test' -%>><%= message('coverage_viewer.lines_covered_per_test') -%></option>
</optgroup>
<% end %>
</select>
</td>

<% if @testable && !@testable.testCases.empty? %>
<% if @coverage_filter=='lines_covered_per_test' %>
<td class="<%= 'first' if first -%>">
<select id="test_case_filter" name="test_case_filter" onchange="applyOptions()">
<option value=""><%= message('lines_covered_per_test') -%></option>
<option value=""><%= message('coverage_viewer.select_test') -%></option>
<% @testable.testCases.each do |test_case| %>
<option value="<%= test_case.key -%>" <%= 'selected' if @test_case_filter==test_case.key -%>><%= test_case.name -%></option>
<% end %>

+ 1
- 1
sonar-server/src/main/webapp/WEB-INF/app/views/test/_testcase_working_view.erb 查看文件

@@ -13,7 +13,7 @@
<% @test_case.covers.sort_by{|cover| cover.testable.component.name}.each do |cover| %>
<tr class="<%= cycle("even", "odd") -%>">
<td>
<a href="<%= ApplicationController.root_context -%>/resource/index/<%= cover.testable.component.key -%>?display_title=true&tab=coverage"
<a href="<%= ApplicationController.root_context -%>/resource/index/<%= cover.testable.component.key -%>?display_title=true&tab=coverage&coverage_filter=lines_covered_per_test&test_case_filter=<%= @test -%>"
onclick="window.open(this.href,'resource','height=800,width=900,scrollbars=1,resizable=1');return false;"><%= cover.testable.component.longName -%>
</a>
</td>

正在加载...
取消
保存