From a0408f68ce3b7eaee7b20cbeb2712201411a7bb2 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Tue, 2 Oct 2012 17:02:31 +0200 Subject: [PATCH] SONAR-2804 Merged coverage --- .../org/sonar/plugins/core/CorePlugin.java | 8 + .../AllTestsBranchCoverageDecorator.java | 72 +++++ .../sensors/AllTestsCoverageDecorator.java | 85 ++++++ .../AllTestsLineCoverageDecorator.java | 73 +++++ .../core/widgets/AllTestsCoverageWidget.java | 43 +++ .../resources/org/sonar/l10n/core.properties | 9 + .../core/widgets/merged_coverage.html.erb | 76 +++++ .../plugins/jacoco/JaCoCoAllTestsSensor.java | 156 ++++++++++ .../sonar/plugins/jacoco/JaCoCoPlugin.java | 3 +- .../org/sonar/api/measures/CoreMetrics.java | 286 ++++++++++++++++++ .../app/controllers/resource_controller.rb | 20 +- .../views/resource/_header_coverage.html.erb | 57 ++-- .../app/views/resource/_options.html.erb | 8 + 13 files changed, 871 insertions(+), 25 deletions(-) create mode 100644 plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AllTestsBranchCoverageDecorator.java create mode 100644 plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AllTestsCoverageDecorator.java create mode 100644 plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AllTestsLineCoverageDecorator.java create mode 100644 plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/AllTestsCoverageWidget.java create mode 100644 plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/merged_coverage.html.erb create mode 100644 plugins/sonar-jacoco-plugin/src/main/java/org/sonar/plugins/jacoco/JaCoCoAllTestsSensor.java diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java index 11899dfbb6b..7dacd86b642 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java @@ -48,6 +48,9 @@ import org.sonar.plugins.core.filters.ProjectFilter; import org.sonar.plugins.core.filters.TreeMapFilter; import org.sonar.plugins.core.security.ApplyProjectRolesDecorator; import org.sonar.plugins.core.security.DefaultResourcePermissions; +import org.sonar.plugins.core.sensors.AllTestsBranchCoverageDecorator; +import org.sonar.plugins.core.sensors.AllTestsCoverageDecorator; +import org.sonar.plugins.core.sensors.AllTestsLineCoverageDecorator; import org.sonar.plugins.core.sensors.BranchCoverageDecorator; import org.sonar.plugins.core.sensors.CheckAlertThresholds; import org.sonar.plugins.core.sensors.CommentDensityDecorator; @@ -86,6 +89,7 @@ import org.sonar.plugins.core.timemachine.ViolationPersisterDecorator; import org.sonar.plugins.core.timemachine.ViolationTrackingDecorator; import org.sonar.plugins.core.web.Lcom4Viewer; import org.sonar.plugins.core.widgets.AlertsWidget; +import org.sonar.plugins.core.widgets.AllTestsCoverageWidget; import org.sonar.plugins.core.widgets.CommentsDuplicationsWidget; import org.sonar.plugins.core.widgets.ComplexityWidget; import org.sonar.plugins.core.widgets.CoverageWidget; @@ -341,6 +345,7 @@ public final class CorePlugin extends SonarPlugin { AlertsWidget.class, CoverageWidget.class, ItCoverageWidget.class, + AllTestsCoverageWidget.class, CommentsDuplicationsWidget.class, DescriptionWidget.class, ComplexityWidget.class, @@ -398,6 +403,9 @@ public final class CorePlugin extends SonarPlugin { ItLineCoverageDecorator.class, ItCoverageDecorator.class, ItBranchCoverageDecorator.class, + AllTestsLineCoverageDecorator.class, + AllTestsCoverageDecorator.class, + AllTestsBranchCoverageDecorator.class, DefaultResourcePermissions.class, ApplyProjectRolesDecorator.class, ExcludedResourceFilter.class, diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AllTestsBranchCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AllTestsBranchCoverageDecorator.java new file mode 100644 index 00000000000..7949cc91e89 --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AllTestsBranchCoverageDecorator.java @@ -0,0 +1,72 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.core.sensors; + +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; + +import java.util.Arrays; +import java.util.List; + +public final class AllTestsBranchCoverageDecorator extends AbstractCoverageDecorator { + + @DependsUpon + public List dependsUponMetrics() { + return Arrays.asList(CoreMetrics.MERGED_UNCOVERED_CONDITIONS, CoreMetrics.MERGED_CONDITIONS_TO_COVER, + CoreMetrics.NEW_MERGED_UNCOVERED_CONDITIONS, CoreMetrics.NEW_MERGED_CONDITIONS_TO_COVER); + } + + @Override + protected Metric getGeneratedMetric() { + return CoreMetrics.MERGED_BRANCH_COVERAGE; + } + + @Override + protected Long countElements(DecoratorContext context) { + return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.MERGED_CONDITIONS_TO_COVER), 0L); + } + + @Override + protected long countCoveredElements(DecoratorContext context) { + long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.MERGED_UNCOVERED_CONDITIONS), 0L); + long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.MERGED_CONDITIONS_TO_COVER), 0L); + return conditions - uncoveredConditions; + } + + @Override + protected Metric getGeneratedMetricForNewCode() { + return CoreMetrics.NEW_MERGED_BRANCH_COVERAGE; + } + + @Override + protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { + return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_MERGED_CONDITIONS_TO_COVER), periodIndex); + } + + @Override + protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { + long uncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_MERGED_UNCOVERED_CONDITIONS), periodIndex, 0L); + long conditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_MERGED_CONDITIONS_TO_COVER), periodIndex, 0L); + return conditions - uncoveredConditions; + } +} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AllTestsCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AllTestsCoverageDecorator.java new file mode 100644 index 00000000000..f83d3291140 --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AllTestsCoverageDecorator.java @@ -0,0 +1,85 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.core.sensors; + +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; + +import java.util.Arrays; +import java.util.Collection; + +public final class AllTestsCoverageDecorator extends AbstractCoverageDecorator { + + @DependsUpon + public Collection usedMetrics() { + return Arrays.asList(CoreMetrics.MERGED_LINES_TO_COVER, CoreMetrics.MERGED_UNCOVERED_LINES, CoreMetrics.NEW_MERGED_LINES_TO_COVER, + CoreMetrics.NEW_MERGED_UNCOVERED_LINES, CoreMetrics.MERGED_CONDITIONS_TO_COVER, CoreMetrics.MERGED_UNCOVERED_CONDITIONS, + CoreMetrics.NEW_MERGED_CONDITIONS_TO_COVER, CoreMetrics.NEW_MERGED_UNCOVERED_CONDITIONS); + } + + @Override + protected Metric getGeneratedMetric() { + return CoreMetrics.MERGED_COVERAGE; + } + + @Override + protected Long countElements(DecoratorContext context) { + long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.MERGED_LINES_TO_COVER), 0L); + long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.MERGED_CONDITIONS_TO_COVER), 0L); + return lines + conditions; + } + + @Override + protected long countCoveredElements(DecoratorContext context) { + long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.MERGED_UNCOVERED_LINES), 0L); + long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.MERGED_LINES_TO_COVER), 0L); + long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.MERGED_UNCOVERED_CONDITIONS), 0L); + long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.MERGED_CONDITIONS_TO_COVER), 0L); + return lines + conditions - uncoveredConditions - uncoveredLines; + } + + + @Override + protected Metric getGeneratedMetricForNewCode() { + return CoreMetrics.NEW_MERGED_COVERAGE; + } + + @Override + protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { + Long newLinesToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_MERGED_LINES_TO_COVER), periodIndex); + if (newLinesToCover != null) { + long newConditionsToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_MERGED_CONDITIONS_TO_COVER), periodIndex, 0L); + return newLinesToCover + newConditionsToCover; + } + return null; + } + + @Override + protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { + long newLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_MERGED_LINES_TO_COVER), periodIndex, 0L); + long newUncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_MERGED_UNCOVERED_LINES), periodIndex, 0L); + long newUncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_MERGED_UNCOVERED_CONDITIONS), periodIndex, 0L); + long newConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_MERGED_CONDITIONS_TO_COVER), periodIndex, 0L); + return newLines + newConditions - newUncoveredConditions - newUncoveredLines; + } +} \ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AllTestsLineCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AllTestsLineCoverageDecorator.java new file mode 100644 index 00000000000..6fb9a973994 --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AllTestsLineCoverageDecorator.java @@ -0,0 +1,73 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.core.sensors; + +import org.sonar.api.batch.DecoratorContext; +import org.sonar.api.batch.DependsUpon; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.MeasureUtils; +import org.sonar.api.measures.Metric; + +import java.util.Arrays; +import java.util.List; + +public final class AllTestsLineCoverageDecorator extends AbstractCoverageDecorator { + + @DependsUpon + public List dependsUponMetrics() { + return Arrays.asList(CoreMetrics.MERGED_UNCOVERED_LINES, CoreMetrics.MERGED_LINES_TO_COVER, CoreMetrics.NEW_MERGED_UNCOVERED_LINES, + CoreMetrics.NEW_MERGED_LINES_TO_COVER); + } + + @Override + protected Metric getGeneratedMetric() { + return CoreMetrics.MERGED_LINE_COVERAGE; + } + + @Override + protected Long countElements(DecoratorContext context) { + return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.MERGED_LINES_TO_COVER), 0L); + } + + @Override + protected long countCoveredElements(DecoratorContext context) { + long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.MERGED_UNCOVERED_LINES), 0L); + long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.MERGED_LINES_TO_COVER), 0L); + return lines - uncoveredLines; + } + + + @Override + protected Metric getGeneratedMetricForNewCode() { + return CoreMetrics.NEW_MERGED_LINE_COVERAGE; + } + + @Override + protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) { + return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_MERGED_LINES_TO_COVER), periodIndex); + } + + @Override + protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) { + long uncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_MERGED_UNCOVERED_LINES), periodIndex, 0L); + long lines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_MERGED_LINES_TO_COVER), periodIndex, 0L); + return lines - uncoveredLines; + } +} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/AllTestsCoverageWidget.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/AllTestsCoverageWidget.java new file mode 100644 index 00000000000..8828ded647a --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/widgets/AllTestsCoverageWidget.java @@ -0,0 +1,43 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.core.widgets; + +import org.sonar.api.web.AbstractRubyTemplate; +import org.sonar.api.web.RubyRailsWidget; +import org.sonar.api.web.UserRole; +import org.sonar.api.web.WidgetCategory; + +@WidgetCategory({ "Tests" }) +@UserRole(UserRole.USER) +public class AllTestsCoverageWidget extends AbstractRubyTemplate implements RubyRailsWidget { + + public String getId() { + return "merged-coverage"; + } + + public String getTitle() { + return "All Tests Coverage"; + } + + @Override + protected String getTemplatePath() { + return "/org/sonar/plugins/core/widgets/merged_coverage.html.erb"; + } +} \ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties index ebba87384b4..563a2c217a0 100644 --- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties @@ -730,6 +730,14 @@ widget.it-coverage.lines_to_cover.suffix=\ lines to cover widget.it-coverage.on_new_code=On new code widget.it-coverage.no_new_lines_to_cover=No new lines to cover +# id of this widget does not use underscore in order to be backward-compatible with previous version of JaCoCo plugin +widget.merged-coverage.name=All tests coverage +widget.merged-coverage.description=Reports on code coverage by all tests +widget.merged-coverage.line_coverage.suffix=\ line coverage +widget.merged-coverage.branch_coverage.suffix=\ branch coverage +widget.merged-coverage.lines_to_cover.suffix=\ lines to cover +widget.merged-coverage.on_new_code=On new code +widget.merged-coverage.no_new_lines_to_cover=No new lines to cover widget.comments_duplications.name=Comments & Duplications widget.comments_duplications.description=Reports on copy/paste and documentation @@ -963,6 +971,7 @@ duplications.collapse=Collapse coverage_viewer.on_new_code=On new code coverage_viewer.unit_tests=Unit Tests coverage_viewer.integration_tests=Integration Tests +coverage_viewer.all_tests=All Tests #------------------------------------------------------------------------------ diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/merged_coverage.html.erb b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/merged_coverage.html.erb new file mode 100644 index 00000000000..8fae498e7ff --- /dev/null +++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/plugins/core/widgets/merged_coverage.html.erb @@ -0,0 +1,76 @@ +<% + coverage_measure=measure('merged_coverage') + if coverage_measure +%> + + + + + +
+
+

<%= message('widget.merged-coverage.name') -%>

+

+ <%= format_measure(coverage_measure, :suffix => '', :url => url_for_drilldown('merged_coverage'), :default => '-') %> + <%= dashboard_configuration.selected_period? ? format_variation(coverage_measure) : trend_icon(coverage_measure) -%> +

+ <% it_line_coverage=measure('merged_line_coverage') + if it_line_coverage %> +

+ <%= format_measure(it_line_coverage, :suffix => message('widget.merged-coverage.line_coverage.suffix'), :url => url_for_drilldown('merged_uncovered_lines', :highlight => 'merged_line_coverage')) %> + <%= dashboard_configuration.selected_period? ? format_variation(it_line_coverage) : trend_icon(it_line_coverage) -%> +

+ <% end %> + <% it_branch_coverage=measure('merged_branch_coverage') + if it_branch_coverage %> +

+ <%= format_measure(it_branch_coverage, :suffix => message('widget.merged-coverage.branch_coverage.suffix'), :url => url_for_drilldown('merged_uncovered_conditions', :highlight => 'merged_branch_coverage')) %> + <%= dashboard_configuration.selected_period? ? format_variation(it_branch_coverage) : trend_icon(it_branch_coverage) -%> +

+ <% end %> +
+
+
+ <% + if dashboard_configuration.selected_period? + new_lines_to_cover_measure=measure('new_merged_lines_to_cover') + if new_lines_to_cover_measure + new_lines=new_lines_to_cover_measure.variation(dashboard_configuration.period_index) + if new_lines + new_coverage=measure('new_merged_coverage') + new_line_coverage=measure('new_merged_line_coverage') + new_branch_coverage=measure('new_merged_branch_coverage') + %> +

<%= message('widget.merged-coverage.on_new_code') -%>:

+ <% if new_lines.to_i==0 %> +

<%= message('widget.merged-coverage.no_new_lines_to_cover') -%>

+ <% else %> + <% if new_coverage %> +

+ + <%= format_variation(new_coverage, :style => 'none', :default => '-') -%> + +

+ <% end %> +

+ <%= format_variation(new_lines_to_cover_measure, :style => 'none', :default => '-') -%><%= message('widget.merged-coverage.lines_to_cover.suffix') -%> +

+ <% if new_line_coverage %> +

+ <%= format_variation(new_line_coverage, :style => 'none', :default => '-') -%><%= message('widget.merged-coverage.line_coverage.suffix') -%> +

+ <% end %> + <% if new_branch_coverage %> +

+ <%= format_variation(new_branch_coverage, :style => 'none', :default => '-') -%><%= message('widget.merged-coverage.branch_coverage.suffix') -%> +

+ <% + end + end + end + end + end + %> +
+
+<% end %> diff --git a/plugins/sonar-jacoco-plugin/src/main/java/org/sonar/plugins/jacoco/JaCoCoAllTestsSensor.java b/plugins/sonar-jacoco-plugin/src/main/java/org/sonar/plugins/jacoco/JaCoCoAllTestsSensor.java new file mode 100644 index 00000000000..57e4cb84dfa --- /dev/null +++ b/plugins/sonar-jacoco-plugin/src/main/java/org/sonar/plugins/jacoco/JaCoCoAllTestsSensor.java @@ -0,0 +1,156 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.jacoco; + +import com.google.common.io.Closeables; +import org.apache.commons.lang.StringUtils; +import org.jacoco.core.data.ExecutionDataReader; +import org.jacoco.core.data.ExecutionDataStore; +import org.jacoco.core.data.ExecutionDataWriter; +import org.jacoco.core.data.SessionInfoStore; +import org.sonar.api.batch.Sensor; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.resources.JavaFile; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.ProjectFileSystem; +import org.sonar.api.utils.SonarException; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collection; + +public class JaCoCoAllTestsSensor implements Sensor { + private static final String MERGED_EXEC = "target/merged.exec"; + + private final JacocoConfiguration configuration; + private final ProjectFileSystem projectFileSystem; + + public JaCoCoAllTestsSensor(JacocoConfiguration configuration, ProjectFileSystem projectFileSystem) { + this.configuration = configuration; + this.projectFileSystem = projectFileSystem; + } + + public boolean shouldExecuteOnProject(Project project) { + return StringUtils.isNotBlank(configuration.getItReportPath()) + && project.getAnalysisType().isDynamic(true); + } + + public void analyse(Project project, SensorContext context) { + mergeReports(); + new AllTestsAnalyzer().analyse(project, context); + } + + private void mergeReports() { + String reportUTs = configuration.getReportPath(); + String reportITs = configuration.getItReportPath(); + String reportAllTests = MERGED_EXEC; + + File baseDir = projectFileSystem.getBasedir(); + File destFile = new File(baseDir, reportAllTests); + + final SessionInfoStore infoStore = new SessionInfoStore(); + final ExecutionDataStore dataStore = new ExecutionDataStore(); + + loadSourceFiles(infoStore, dataStore, new File(baseDir, reportUTs), new File(baseDir, reportITs)); + + BufferedOutputStream outputStream = null; + try { + outputStream = new BufferedOutputStream(new FileOutputStream(destFile)); + ExecutionDataWriter dataWriter = new ExecutionDataWriter(outputStream); + + infoStore.accept(dataWriter); + dataStore.accept(dataWriter); + } catch (IOException e) { + throw new SonarException(String.format("Unable to write merged file %s", destFile.getAbsolutePath()), e); + } finally { + Closeables.closeQuietly(outputStream); + } + } + + private void loadSourceFiles(SessionInfoStore infoStore, ExecutionDataStore dataStore, File... files) { + for (File file : files) { + InputStream resourceStream = null; + try { + resourceStream = new BufferedInputStream(new FileInputStream(file)); + ExecutionDataReader reader = new ExecutionDataReader(resourceStream); + reader.setSessionInfoVisitor(infoStore); + reader.setExecutionDataVisitor(dataStore); + reader.read(); + } catch (final IOException e) { + throw new SonarException(String.format("Unable to read %s", file.getAbsolutePath()), e); + } finally { + Closeables.closeQuietly(resourceStream); + } + } + } + + class AllTestsAnalyzer extends AbstractAnalyzer { + @Override + protected String getReportPath(Project project) { + return MERGED_EXEC; + } + + @Override + protected String getExcludes(Project project) { + return configuration.getExcludes(); + } + + @Override + protected void saveMeasures(SensorContext context, JavaFile resource, Collection measures) { + for (Measure measure : measures) { + Measure mergedMeasure = convertForIT(measure); + if (mergedMeasure != null) { + context.saveMeasure(resource, mergedMeasure); + } + } + } + + private Measure convertForIT(Measure measure) { + if (CoreMetrics.LINES_TO_COVER.equals(measure.getMetric())) { + return new Measure(CoreMetrics.MERGED_LINES_TO_COVER, measure.getValue()); + } else if (CoreMetrics.UNCOVERED_LINES.equals(measure.getMetric())) { + return new Measure(CoreMetrics.MERGED_UNCOVERED_LINES, measure.getValue()); + } else if (CoreMetrics.COVERAGE_LINE_HITS_DATA.equals(measure.getMetric())) { + return new Measure(CoreMetrics.MERGED_COVERAGE_LINE_HITS_DATA, measure.getData()); + } else if (CoreMetrics.CONDITIONS_TO_COVER.equals(measure.getMetric())) { + return new Measure(CoreMetrics.MERGED_CONDITIONS_TO_COVER, measure.getValue()); + } else if (CoreMetrics.UNCOVERED_CONDITIONS.equals(measure.getMetric())) { + return new Measure(CoreMetrics.MERGED_UNCOVERED_CONDITIONS, measure.getValue()); + } else if (CoreMetrics.COVERED_CONDITIONS_BY_LINE.equals(measure.getMetric())) { + return new Measure(CoreMetrics.MERGED_COVERED_CONDITIONS_BY_LINE, measure.getData()); + } else if (CoreMetrics.CONDITIONS_BY_LINE.equals(measure.getMetric())) { + return new Measure(CoreMetrics.MERGED_CONDITIONS_BY_LINE, measure.getData()); + } + return null; + } + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/plugins/sonar-jacoco-plugin/src/main/java/org/sonar/plugins/jacoco/JaCoCoPlugin.java b/plugins/sonar-jacoco-plugin/src/main/java/org/sonar/plugins/jacoco/JaCoCoPlugin.java index 8fd1e6c5cbd..9a6a2016982 100644 --- a/plugins/sonar-jacoco-plugin/src/main/java/org/sonar/plugins/jacoco/JaCoCoPlugin.java +++ b/plugins/sonar-jacoco-plugin/src/main/java/org/sonar/plugins/jacoco/JaCoCoPlugin.java @@ -39,6 +39,7 @@ public class JaCoCoPlugin extends SonarPlugin { // Unit tests JaCoCoSensor.class, // Integration tests - JaCoCoItSensor.class); + JaCoCoItSensor.class, + JaCoCoAllTestsSensor.class); } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java index 9ac19fe6034..a03ab232ef8 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java @@ -40,6 +40,7 @@ public final class CoreMetrics { public static final String DOMAIN_SIZE = "Size"; public static final String DOMAIN_TESTS = "Tests"; public static final String DOMAIN_INTEGRATION_TESTS = "Integration Tests"; + public static final String DOMAIN_MERGED_TESTS = "Merged Tests"; public static final String DOMAIN_COMPLEXITY = "Complexity"; public static final String DOMAIN_DOCUMENTATION = "Documentation"; public static final String DOMAIN_RULES = "Rules"; @@ -957,6 +958,291 @@ public final class CoreMetrics { .setDeleteHistoricalData(true) .create(); + // -------------------------------------------------------------------------------------------------------------------- + // + // MERGED TESTS + // + // -------------------------------------------------------------------------------------------------------------------- + + /** + * @since 3.3 + */ + public static final String MERGED_COVERAGE_KEY = "merged_coverage"; + + /** + * @since 3.3 + */ + public static final Metric MERGED_COVERAGE = new Metric.Builder(MERGED_COVERAGE_KEY, "All Tests Coverage", Metric.ValueType.PERCENT) + .setDescription("Coverage by All Tests") + .setDirection(Metric.DIRECTION_BETTER) + .setQualitative(true) + .setDomain(DOMAIN_MERGED_TESTS) + .setWorstValue(0.0) + .setBestValue(100.0) + .create(); + + /** + * @since 3.3 + */ + public static final String NEW_MERGED_COVERAGE_KEY = "new_merged_coverage"; + + /** + * @since 3.3 + */ + public static final Metric NEW_MERGED_COVERAGE = new Metric.Builder(NEW_MERGED_COVERAGE_KEY, "New Coverage by All Tests", Metric.ValueType.PERCENT) + .setDescription("All Tests Coverage of new/changed code") + .setDirection(Metric.DIRECTION_BETTER) + .setQualitative(true) + .setDomain(DOMAIN_MERGED_TESTS) + .setWorstValue(0.0) + .setBestValue(100.0) + .setDeleteHistoricalData(true) + .create(); + + /** + * @since 3.3 + */ + public static final String MERGED_LINES_TO_COVER_KEY = "merged_lines_to_cover"; + + /** + * @since 3.3 + */ + public static final Metric MERGED_LINES_TO_COVER = new Metric.Builder(MERGED_LINES_TO_COVER_KEY, "All Tests Lines to Cover", Metric.ValueType.INT) + .setDescription("Lines to cover by All Tests") + .setDirection(Metric.DIRECTION_BETTER) + .setDomain(DOMAIN_MERGED_TESTS) + .setQualitative(false) + .setFormula(new SumChildValuesFormula(false)) + .setHidden(true) + .setDeleteHistoricalData(true) + .create(); + + /** + * @since 3.3 + */ + public static final String NEW_MERGED_LINES_TO_COVER_KEY = "new_merged_lines_to_cover"; + + /** + * @since 3.3 + */ + public static final Metric NEW_MERGED_LINES_TO_COVER = new Metric.Builder(NEW_MERGED_LINES_TO_COVER_KEY, "New Lines to Cover by All Tests", Metric.ValueType.INT) + .setDescription("New lines to cover by All Tests") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(DOMAIN_MERGED_TESTS) + .setFormula(new SumChildValuesFormula(false)) + .setDeleteHistoricalData(true) + .create(); + + /** + * @since 3.3 + */ + public static final String MERGED_UNCOVERED_LINES_KEY = "merged_uncovered_lines"; + + /** + * @since 3.3 + */ + public static final Metric MERGED_UNCOVERED_LINES = new Metric.Builder(MERGED_UNCOVERED_LINES_KEY, "All Tests Uncovered Lines", Metric.ValueType.INT) + .setDescription("All Tests uncovered lines") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(DOMAIN_MERGED_TESTS) + .setFormula(new SumChildValuesFormula(false)) + .create(); + + /** + * @since 3.3 + */ + public static final String NEW_MERGED_UNCOVERED_LINES_KEY = "new_merged_uncovered_lines"; + + /** + * @since 3.3 + */ + public static final Metric NEW_MERGED_UNCOVERED_LINES = new Metric.Builder(NEW_MERGED_UNCOVERED_LINES_KEY, "New Uncovered Lines by All Tests", Metric.ValueType.INT) + .setDescription("New uncovered lines by All Tests") + .setDirection(Metric.DIRECTION_WORST) + .setDomain(DOMAIN_MERGED_TESTS) + .setFormula(new SumChildValuesFormula(false)) + .setBestValue(0.0) + .setDeleteHistoricalData(true) + .create(); + + /** + * @since 3.3 + */ + public static final String MERGED_LINE_COVERAGE_KEY = "merged_line_coverage"; + + /** + * @since 3.3 + */ + public static final Metric MERGED_LINE_COVERAGE = new Metric.Builder(MERGED_LINE_COVERAGE_KEY, "All Tests Line coverage", Metric.ValueType.PERCENT) + .setDescription("All Tests line coverage") + .setDirection(Metric.DIRECTION_BETTER) + .setQualitative(true) + .setDomain(DOMAIN_MERGED_TESTS) + .create(); + + /** + * @since 3.3 + */ + public static final String NEW_MERGED_LINE_COVERAGE_KEY = "new_merged_line_coverage"; + + /** + * @since 3.3 + */ + public static final Metric NEW_MERGED_LINE_COVERAGE = new Metric.Builder(NEW_MERGED_LINE_COVERAGE_KEY, "New Line Coverage by All Tests", Metric.ValueType.PERCENT) + .setDescription("Line Coverage by All Tests of added/changed code") + .setDirection(Metric.DIRECTION_BETTER) + .setQualitative(true) + .setWorstValue(0.0) + .setBestValue(100.0) + .setDomain(DOMAIN_MERGED_TESTS) + .setDeleteHistoricalData(true) + .create(); + + /** + * @since 3.3 + */ + public static final String MERGED_COVERAGE_LINE_HITS_DATA_KEY = "merged_coverage_line_hits_data"; + + /** + * @since 3.3 + */ + public static final Metric MERGED_COVERAGE_LINE_HITS_DATA = new Metric.Builder(MERGED_COVERAGE_LINE_HITS_DATA_KEY, "All Tests Coverage Hits Data", Metric.ValueType.DATA) + .setDescription("All Tests Code coverage line hits data") + .setDirection(Metric.DIRECTION_NONE) + .setQualitative(false) + .setDomain(DOMAIN_MERGED_TESTS) + .setDeleteHistoricalData(true) + .create(); + + /** + * @since 3.3 + */ + public static final String MERGED_CONDITIONS_TO_COVER_KEY = "merged_conditions_to_cover"; + + /** + * @since 3.3 + */ + public static final Metric MERGED_CONDITIONS_TO_COVER = new Metric.Builder(MERGED_CONDITIONS_TO_COVER_KEY, "All Tests Branches to Cover", Metric.ValueType.INT) + .setDescription("All Tests Conditions to cover") + .setDirection(Metric.DIRECTION_BETTER) + .setQualitative(false) + .setDomain(DOMAIN_MERGED_TESTS) + .setFormula(new SumChildValuesFormula(false)) + .setHidden(true) + .setDeleteHistoricalData(true) + .create(); + + /** + * @since 3.3 + */ + public static final String NEW_MERGED_CONDITIONS_TO_COVER_KEY = "new_merged_conditions_to_cover"; + + /** + * @since 3.3 + */ + public static final Metric NEW_MERGED_CONDITIONS_TO_COVER = new Metric.Builder(NEW_MERGED_CONDITIONS_TO_COVER_KEY, "New Conditions to Cover by All Tests", Metric.ValueType.INT) + .setDescription("New conditions to cover by All Tests") + .setDomain(DOMAIN_MERGED_TESTS) + .setFormula(new SumChildValuesFormula(false)) + .setDeleteHistoricalData(true) + .create(); + + /** + * @since 3.3 + */ + public static final String MERGED_UNCOVERED_CONDITIONS_KEY = "merged_uncovered_conditions"; + + /** + * @since 3.3 + */ + public static final Metric MERGED_UNCOVERED_CONDITIONS = new Metric.Builder(MERGED_UNCOVERED_CONDITIONS_KEY, "All Tests Uncovered Branches", Metric.ValueType.INT) + .setDescription("All Tests Uncovered conditions") + .setDirection(Metric.DIRECTION_WORST) + .setDomain(DOMAIN_MERGED_TESTS) + .setFormula(new SumChildValuesFormula(false)) + .create(); + + /** + * @since 3.3 + */ + public static final String NEW_MERGED_UNCOVERED_CONDITIONS_KEY = "new_merged_uncovered_conditions"; + + /** + * @since 3.3 + */ + public static final Metric NEW_MERGED_UNCOVERED_CONDITIONS = new Metric.Builder(NEW_MERGED_UNCOVERED_CONDITIONS_KEY, "New Uncovered Conditions by All Tests", Metric.ValueType.INT) + .setDescription("New uncovered conditions by All Tests") + .setDirection(Metric.DIRECTION_WORST) + .setDomain(DOMAIN_MERGED_TESTS) + .setFormula(new SumChildValuesFormula(false)) + .setBestValue(0.0) + .setDeleteHistoricalData(true) + .create(); + + /** + * @since 3.3 + */ + public static final String MERGED_BRANCH_COVERAGE_KEY = "merged_branch_coverage"; + + /** + * @since 3.3 + */ + public static final Metric MERGED_BRANCH_COVERAGE = new Metric.Builder(MERGED_BRANCH_COVERAGE_KEY, "All Tests Branch Coverage", Metric.ValueType.PERCENT) + .setDescription("All Tests Branch coverage") + .setDirection(Metric.DIRECTION_BETTER) + .setQualitative(true) + .setDomain(DOMAIN_MERGED_TESTS) + .setWorstValue(0.0) + .setBestValue(100.0) + .create(); + + /** + * @since 3.3 + */ + public static final String NEW_MERGED_BRANCH_COVERAGE_KEY = "new_merged_branch_coverage"; + + /** + * @since 3.3 + */ + public static final Metric NEW_MERGED_BRANCH_COVERAGE = new Metric.Builder(NEW_MERGED_BRANCH_COVERAGE_KEY, "New Branch Coverage by All Tests", Metric.ValueType.PERCENT) + .setDescription("Branch coverage by All Tests of new/changed code") + .setDirection(Metric.DIRECTION_BETTER) + .setQualitative(true) + .setDomain(DOMAIN_MERGED_TESTS) + .setWorstValue(0.0) + .setBestValue(100.0) + .setDeleteHistoricalData(true) + .create(); + + /** + * @since 3.3 + */ + public static final String MERGED_CONDITIONS_BY_LINE_KEY = "merged_conditions_by_line"; + + /** + * @since 3.3 + */ + public static final Metric MERGED_CONDITIONS_BY_LINE = new Metric.Builder(MERGED_CONDITIONS_BY_LINE_KEY, "All Tests Branches by Line", Metric.ValueType.DATA) + .setDomain(DOMAIN_MERGED_TESTS) + .setDeleteHistoricalData(true) + .create(); + + /** + * @since 3.3 + */ + public static final String MERGED_COVERED_CONDITIONS_BY_LINE_KEY = "merged_covered_conditions_by_line"; + + /** + * @since 3.3 + */ + public static final Metric MERGED_COVERED_CONDITIONS_BY_LINE = new Metric.Builder(MERGED_COVERED_CONDITIONS_BY_LINE_KEY, "All Tests Covered Branches by Line", Metric.ValueType.DATA) + .setDomain(DOMAIN_MERGED_TESTS) + .setDeleteHistoricalData(true) + .create(); + + // -------------------------------------------------------------------------------------------------------------------- // // DUPLICATIONS diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb index a9e54122f81..69f3fe56700 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb @@ -177,11 +177,15 @@ class ResourceController < ApplicationController load_sources() @display_coverage = true @display_it_coverage = (!@snapshot.measure('it_coverage').nil?) + @display_all_tests_coverage = (!@snapshot.measure('merged_coverage').nil?) @expandable = (@lines!=nil) if @lines metric = Metric.by_key(params[:coverage_filter]||params[:metric]) @coverage_filter = (metric ? metric.key : 'coverage') - it_prefix = (@coverage_filter.start_with?('it_') ? 'it_' : '') + + it_prefix = '' + it_prefix = 'it_' if @coverage_filter.start_with?('it_') + it_prefix = 'merged_' if @coverage_filter.start_with?('merged_') @hits_by_line = load_distribution("#{it_prefix}coverage_line_hits_data") @conditions_by_line = load_distribution("#{it_prefix}conditions_by_line") @@ -212,24 +216,30 @@ class ResourceController < ApplicationController 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 || - 'new_it_lines_to_cover'==@coverage_filter || 'new_it_coverage'==@coverage_filter || 'new_it_line_coverage'==@coverage_filter) + 'new_it_lines_to_cover'==@coverage_filter || 'new_it_coverage'==@coverage_filter || 'new_it_line_coverage'==@coverage_filter + 'merged_lines_to_cover'==@coverage_filter || 'merged_coverage'==@coverage_filter || 'merged_line_coverage'==@coverage_filter || + 'new_merged_lines_to_cover'==@coverage_filter || 'new_merged_coverage'==@coverage_filter || 'new_merged_line_coverage'==@coverage_filter) @coverage_filter = "#{it_prefix}lines_to_cover" filter_lines { |line| line.hits && line.after(to) } elsif ('uncovered_lines'==@coverage_filter || 'new_uncovered_lines'==@coverage_filter || - 'it_uncovered_lines'==@coverage_filter || 'new_it_uncovered_lines'==@coverage_filter) + 'it_uncovered_lines'==@coverage_filter || 'new_it_uncovered_lines'==@coverage_filter + 'merged_uncovered_lines'==@coverage_filter || 'new_merged_uncovered_lines'==@coverage_filter) @coverage_filter = "#{it_prefix}uncovered_lines" filter_lines { |line| line.hits && line.hits==0 && line.after(to) } elsif ('conditions_to_cover'==@coverage_filter || 'branch_coverage'==@coverage_filter || 'new_conditions_to_cover'==@coverage_filter || 'new_branch_coverage'==@coverage_filter || 'it_conditions_to_cover'==@coverage_filter || 'it_branch_coverage'==@coverage_filter || - 'new_it_conditions_to_cover' == @coverage_filter || 'new_it_branch_coverage'==@coverage_filter) + 'new_it_conditions_to_cover' == @coverage_filter || 'new_it_branch_coverage'==@coverage_filter + 'merged_conditions_to_cover'==@coverage_filter || 'merged_branch_coverage'==@coverage_filter || + 'new_merged_conditions_to_cover' == @coverage_filter || 'new_merged_branch_coverage'==@coverage_filter) @coverage_filter="#{it_prefix}conditions_to_cover" filter_lines { |line| line.conditions && line.conditions>0 && line.after(to) } elsif ('uncovered_conditions' == @coverage_filter || 'new_uncovered_conditions' == @coverage_filter || - 'it_uncovered_conditions'==@coverage_filter || 'new_it_uncovered_conditions' == @coverage_filter) + 'it_uncovered_conditions'==@coverage_filter || 'new_it_uncovered_conditions' == @coverage_filter + 'merged_uncovered_conditions'==@coverage_filter || 'new_merged_uncovered_conditions' == @coverage_filter) @coverage_filter="#{it_prefix}uncovered_conditions" filter_lines { |line| line.conditions && line.covered_conditions && line.covered_conditions <% else %> - <% if @display_it_coverage %> + <% if @display_it_coverage || @display_all_tests_coverage %> @@ -103,24 +103,43 @@ <%= render :partial => 'measure', :locals => {:measure => measure('uncovered_conditions'), :title => Metric.name_for('uncovered_conditions'), :ratio => measure('conditions_to_cover')} -%> - <% if @display_it_coverage %> - - - - - - - <%= render :partial => 'measure', :locals => {:measure => measure('it_line_coverage'), :title => Metric.name_for('it_line_coverage')} -%> - - <%= render :partial => 'measure', :locals => {:measure => measure('it_branch_coverage'), :title => Metric.name_for('it_branch_coverage')} -%> - - - - <%= render :partial => 'measure', :locals => {:measure => measure('it_uncovered_lines'), :title => Metric.name_for('it_uncovered_lines'), :ratio => measure('it_lines_to_cover')} -%> - - <%= render :partial => 'measure', :locals => {:measure => measure('it_uncovered_conditions'), :title => Metric.name_for('it_uncovered_conditions'), :ratio => measure('it_conditions_to_cover')} -%> - - <% end %> + <% if @display_it_coverage %> + + + + + + + <%= render :partial => 'measure', :locals => {:measure => measure('it_line_coverage'), :title => Metric.name_for('it_line_coverage')} -%> + + <%= render :partial => 'measure', :locals => {:measure => measure('it_branch_coverage'), :title => Metric.name_for('it_branch_coverage')} -%> + + + + <%= render :partial => 'measure', :locals => {:measure => measure('it_uncovered_lines'), :title => Metric.name_for('it_uncovered_lines'), :ratio => measure('it_lines_to_cover')} -%> + + <%= render :partial => 'measure', :locals => {:measure => measure('it_uncovered_conditions'), :title => Metric.name_for('it_uncovered_conditions'), :ratio => measure('it_conditions_to_cover')} -%> + + <% end %> + + <% if @display_all_tests_coverage %> + + + + + + + <%= render :partial => 'measure', :locals => {:measure => measure('merged_line_coverage'), :title => Metric.name_for('merged_line_coverage')} -%> + + <%= render :partial => 'measure', :locals => {:measure => measure('merged_branch_coverage'), :title => Metric.name_for('merged_branch_coverage')} -%> + + + + <%= render :partial => 'measure', :locals => {:measure => measure('merged_uncovered_lines'), :title => Metric.name_for('merged_uncovered_lines'), :ratio => measure('merged_lines_to_cover')} -%> + + <%= render :partial => 'measure', :locals => {:measure => measure('merged_uncovered_conditions'), :title => Metric.name_for('merged_uncovered_conditions'), :ratio => measure('merged_conditions_to_cover')} -%> + + <% end %>
<%= message('coverage_viewer.unit_tests') -%>

<%= message('coverage_viewer.integration_tests') -%>
<%= format_measure('it_coverage', :default => '-') -%>

<%= message('coverage_viewer.integration_tests') -%>
<%= format_measure('it_coverage', :default => '-') -%>

<%= message('coverage_viewer.all_tests') -%>
<%= format_measure('merged_coverage', :default => '-') -%>
<% end %> diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_options.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_options.html.erb index c0754df974b..07e4d531b24 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_options.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/resource/_options.html.erb @@ -81,6 +81,14 @@ <% end %> + <% if @display_all_tests_coverage %> + + + + + + + <% end %> <% first=false -- 2.39.5