]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-2952 move integration test metrics from jacoco plugin to core
authorsimonbrandhof <simon.brandhof@gmail.com>
Tue, 1 Nov 2011 21:01:14 +0000 (22:01 +0100)
committersimonbrandhof <simon.brandhof@gmail.com>
Tue, 1 Nov 2011 21:01:31 +0000 (22:01 +0100)
17 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItBranchCoverageDecorator.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItCoverageDecorator.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItLineCoverageDecorator.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageAggregator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java [new file with mode: 0644]
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java
plugins/sonar-jacoco-plugin/src/main/java/org/sonar/plugins/jacoco/JaCoCoPlugin.java
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/core.properties
sonar-core/src/main/java/org/sonar/jpa/session/CustomHibernateConnectionProvider.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb
sonar-server/src/main/webapp/WEB-INF/app/views/resource/_header_coverage.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/resource/_options.html.erb

index 82e3a1c872304ad6e0608811150b16913142278a..00ea454707733abb20691c958a755a88ff18e6da 100644 (file)
@@ -268,6 +268,9 @@ public class CorePlugin extends SonarPlugin {
     extensions.add(LineCoverageDecorator.class);
     extensions.add(CoverageDecorator.class);
     extensions.add(BranchCoverageDecorator.class);
+    extensions.add(ItLineCoverageDecorator.class);
+    extensions.add(ItCoverageDecorator.class);
+    extensions.add(ItBranchCoverageDecorator.class);
     extensions.add(ApplyProjectRolesDecorator.class);
     extensions.add(ExcludedResourceFilter.class);
     extensions.add(CommentDensityDecorator.class);
@@ -286,6 +289,7 @@ public class CorePlugin extends SonarPlugin {
     extensions.add(NewViolationsDecorator.class);
     extensions.add(TimeMachineConfigurationPersister.class);
     extensions.add(NewCoverageFileAnalyzer.class);
+    extensions.add(NewItCoverageFileAnalyzer.class);
     extensions.add(NewCoverageAggregator.class);
 
     return extensions;
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItBranchCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItBranchCoverageDecorator.java
new file mode 100644 (file)
index 0000000..90a6243
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 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 ItBranchCoverageDecorator extends AbstractCoverageDecorator {
+
+  @DependsUpon
+  public List<Metric> dependsUponMetrics() {
+    return Arrays.asList(CoreMetrics.IT_UNCOVERED_CONDITIONS, CoreMetrics.IT_CONDITIONS_TO_COVER,
+        CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS, CoreMetrics.NEW_IT_CONDITIONS_TO_COVER);
+  }
+
+  @Override
+  protected Metric getGeneratedMetric() {
+    return CoreMetrics.IT_BRANCH_COVERAGE;
+  }
+
+  @Override
+  protected Long countElements(DecoratorContext context) {
+    return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER), 0L);
+  }
+
+  @Override
+  protected long countCoveredElements(DecoratorContext context) {
+    long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_UNCOVERED_CONDITIONS), 0L);
+    long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER), 0L);
+    return conditions - uncoveredConditions;
+  }
+
+  @Override
+  protected Metric getGeneratedMetricForNewCode() {
+    return CoreMetrics.NEW_IT_BRANCH_COVERAGE;
+  }
+
+  @Override
+  protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) {
+    return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_CONDITIONS_TO_COVER), periodIndex);
+  }
+
+  @Override
+  protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) {
+    long uncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS), periodIndex, 0L);
+    long conditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_CONDITIONS_TO_COVER), periodIndex, 0L);
+    return conditions - uncoveredConditions;
+  }
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItCoverageDecorator.java
new file mode 100644 (file)
index 0000000..ce538aa
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 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 ItCoverageDecorator extends AbstractCoverageDecorator {
+
+  @DependsUpon
+  public Collection<Metric> usedMetrics() {
+    return Arrays.asList(CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.NEW_IT_LINES_TO_COVER,
+        CoreMetrics.NEW_IT_UNCOVERED_LINES, CoreMetrics.IT_CONDITIONS_TO_COVER, CoreMetrics.IT_UNCOVERED_CONDITIONS,
+        CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS);
+  }
+
+  @Override
+  protected Metric getGeneratedMetric() {
+    return CoreMetrics.IT_COVERAGE;
+  }
+
+  @Override
+  protected Long countElements(DecoratorContext context) {
+    long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER), 0L);
+    long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER), 0L);
+    return lines + conditions;
+  }
+
+  @Override
+  protected long countCoveredElements(DecoratorContext context) {
+    long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_UNCOVERED_LINES), 0L);
+    long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER), 0L);
+    long uncoveredConditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_UNCOVERED_CONDITIONS), 0L);
+    long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_CONDITIONS_TO_COVER), 0L);
+    return lines + conditions - uncoveredConditions - uncoveredLines;
+  }
+
+
+  @Override
+  protected Metric getGeneratedMetricForNewCode() {
+    return CoreMetrics.NEW_IT_COVERAGE;
+  }
+
+  @Override
+  protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) {
+    Long newLinesToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER), periodIndex);
+    if (newLinesToCover != null) {
+      long newConditionsToCover = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_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_IT_LINES_TO_COVER), periodIndex, 0L);
+    long newUncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_LINES), periodIndex, 0L);
+    long newUncoveredConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS), periodIndex, 0L);
+    long newConditions = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_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/ItLineCoverageDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItLineCoverageDecorator.java
new file mode 100644 (file)
index 0000000..53c46fd
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 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 ItLineCoverageDecorator extends AbstractCoverageDecorator {
+
+  @DependsUpon
+  public List<Metric> dependsUponMetrics() {
+    return Arrays.asList(CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_LINES,
+        CoreMetrics.NEW_IT_LINES_TO_COVER);
+  }
+
+  @Override
+  protected Metric getGeneratedMetric() {
+    return CoreMetrics.IT_LINE_COVERAGE;
+  }
+
+  @Override
+  protected Long countElements(DecoratorContext context) {
+    return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER), 0L);
+  }
+
+  @Override
+  protected long countCoveredElements(DecoratorContext context) {
+    long uncoveredLines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_UNCOVERED_LINES), 0L);
+    long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.IT_LINES_TO_COVER), 0L);
+    return lines - uncoveredLines;
+  }
+
+
+  @Override
+  protected Metric getGeneratedMetricForNewCode() {
+    return CoreMetrics.NEW_IT_LINE_COVERAGE;
+  }
+
+  @Override
+  protected Long countElementsForNewCode(DecoratorContext context, int periodIndex) {
+    return MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER), periodIndex);
+  }
+
+  @Override
+  protected long countCoveredElementsForNewCode(DecoratorContext context, int periodIndex) {
+    long uncoveredLines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_UNCOVERED_LINES), periodIndex, 0L);
+    long lines = MeasureUtils.getVariationAsLong(context.getMeasure(CoreMetrics.NEW_IT_LINES_TO_COVER), periodIndex, 0L);
+    return lines - uncoveredLines;
+  }
+}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java
new file mode 100644 (file)
index 0000000..f5740ff
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 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.timemachine;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.apache.commons.lang.ObjectUtils;
+import org.sonar.api.batch.*;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Resource;
+import org.sonar.api.resources.Scopes;
+import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.batch.components.PastSnapshot;
+import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.core.NotDryRun;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @since 2.7
+ */
+@NotDryRun
+@DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE)
+public abstract class AbstractNewCoverageFileAnalyzer implements Decorator {
+
+  private List<PeriodStruct> structs;
+
+  public AbstractNewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration) {
+    structs = Lists.newArrayList();
+    for (PastSnapshot pastSnapshot : timeMachineConfiguration.getProjectPastSnapshots()) {
+      structs.add(new PeriodStruct(pastSnapshot));
+    }
+  }
+
+  AbstractNewCoverageFileAnalyzer(List<PeriodStruct> structs) {
+    this.structs = structs;
+  }
+
+  public abstract Metric getCoverageLineHitsDataMetric();
+
+  public abstract Metric getConditionsByLineMetric();
+
+  public abstract Metric getCoveredConditionsByLineMetric();
+
+  public abstract  Metric getNewLinesToCoverMetric();
+
+  public abstract Metric getNewUncoveredLinesMetric();
+
+  public abstract Metric getNewConditionsToCoverMetric();
+
+  public abstract Metric getNewUncoveredConditionsMetric();
+
+  public boolean shouldExecuteOnProject(Project project) {
+    return project.isLatestAnalysis() && !structs.isEmpty();
+  }
+
+  private boolean shouldDecorate(Resource resource) {
+    return Scopes.isFile(resource) && !Qualifiers.UNIT_TEST_FILE.equals(resource.getQualifier());
+  }
+
+  @DependsUpon
+  public List<Metric> dependsOnMetrics() {
+
+    return Arrays.asList(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE,
+      getCoverageLineHitsDataMetric(), getConditionsByLineMetric(), getCoveredConditionsByLineMetric());
+  }
+
+  @DependedUpon
+  public List<Metric> generatesNewCoverageMetrics() {
+    return Arrays.asList(getNewLinesToCoverMetric(), getNewUncoveredLinesMetric(), getNewConditionsToCoverMetric(), getNewUncoveredConditionsMetric());
+  }
+
+  public void decorate(Resource resource, DecoratorContext context) {
+    if (shouldDecorate(resource)) {
+      doDecorate(context);
+    }
+  }
+
+  void doDecorate(DecoratorContext context) {
+    if (parse(context)) {
+      compute(context);
+    }
+  }
+
+  private boolean parse(DecoratorContext context) {
+    Measure lastCommits = context.getMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE);
+    Measure hitsByLineMeasure = context.getMeasure(getCoverageLineHitsDataMetric());
+
+    if (lastCommits != null && lastCommits.hasData() && hitsByLineMeasure != null && hitsByLineMeasure.hasData()) {
+      Map<Integer, Date> datesByLine = KeyValueFormat.parseIntDateTime(lastCommits.getData());
+      Map<Integer, Integer> hitsByLine = parseCountByLine(hitsByLineMeasure);
+      Map<Integer, Integer> conditionsByLine = parseCountByLine(context.getMeasure(getConditionsByLineMetric()));
+      Map<Integer, Integer> coveredConditionsByLine = parseCountByLine(context.getMeasure(getCoveredConditionsByLineMetric()));
+
+      reset();
+
+      for (Map.Entry<Integer, Integer> entry : hitsByLine.entrySet()) {
+        int lineId = entry.getKey();
+        int hits = entry.getValue();
+        int conditions = (Integer) ObjectUtils.defaultIfNull(conditionsByLine.get(lineId), 0);
+        int coveredConditions = (Integer) ObjectUtils.defaultIfNull(coveredConditionsByLine.get(lineId), 0);
+        Date date = datesByLine.get(lineId);
+        for (PeriodStruct struct : structs) {
+          struct.analyze(date, hits, conditions, coveredConditions);
+        }
+      }
+
+      return true;
+    }
+    return false;
+  }
+
+  private void reset() {
+    for (PeriodStruct struct : structs) {
+      struct.reset();
+    }
+  }
+
+  private void compute(DecoratorContext context) {
+    Measure newLines = new Measure(getNewLinesToCoverMetric());
+    Measure newUncoveredLines = new Measure(getNewUncoveredLinesMetric());
+    Measure newConditions = new Measure(getNewConditionsToCoverMetric());
+    Measure newUncoveredConditions = new Measure(getNewUncoveredConditionsMetric());
+
+    for (PeriodStruct struct : structs) {
+      newLines.setVariation(struct.index, (double) struct.newLines);
+      newUncoveredLines.setVariation(struct.index, (double) (struct.newLines - struct.newCoveredLines));
+      newConditions.setVariation(struct.index, (double) struct.newConditions);
+      newUncoveredConditions.setVariation(struct.index, (double) struct.newConditions - struct.newCoveredConditions);
+    }
+
+    context.saveMeasure(newLines);
+    context.saveMeasure(newUncoveredLines);
+    context.saveMeasure(newConditions);
+    context.saveMeasure(newUncoveredConditions);
+  }
+
+  private Map<Integer, Integer> parseCountByLine(Measure measure) {
+    if (measure != null && measure.hasData()) {
+      return KeyValueFormat.parseIntInt(measure.getData());
+    }
+    return Maps.newHashMap();
+  }
+
+  public static final class PeriodStruct {
+    int index;
+    Date date;
+    int newLines = 0, newCoveredLines = 0, newConditions = 0, newCoveredConditions = 0;
+
+    PeriodStruct(PastSnapshot pastSnapshot) {
+      this.index = pastSnapshot.getIndex();
+      this.date = pastSnapshot.getTargetDate();
+    }
+
+    PeriodStruct(int index, Date date) {
+      this.index = index;
+      this.date = date;
+    }
+
+    void reset() {
+      newLines = 0;
+      newCoveredLines = 0;
+      newConditions = 0;
+      newCoveredConditions = 0;
+    }
+
+    void analyze(Date lineDate, int hits, int conditions, int coveredConditions) {
+      if (lineDate == null) {
+        // TODO warning
+
+      } else if (date == null || lineDate.after(date)) {
+        // TODO test if string comparison is faster or not
+        addLine(hits > 0);
+        addConditions(conditions, coveredConditions);
+      }
+    }
+
+    void addLine(boolean covered) {
+      newLines += 1;
+      if (covered) {
+        newCoveredLines += 1;
+      }
+    }
+
+    void addConditions(int count, int countCovered) {
+      newConditions += count;
+      if (count > 0) {
+        newCoveredConditions += countCovered;
+      }
+    }
+  }
+}
index 15d0e7a1f68b37ef15402687cf33b80191d54bdb..c4ffc776450dea9dbb15a44eb22d6c2e80973a0c 100644 (file)
@@ -44,8 +44,9 @@ public final class NewCoverageAggregator implements Decorator {
 
   @DependedUpon
   public List<Metric> generatesNewCoverageMetrics() {
-    return Arrays.asList(CoreMetrics.NEW_LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES,
-        CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS);
+    return Arrays.asList(
+      CoreMetrics.NEW_LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS,
+      CoreMetrics.NEW_IT_LINES_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_LINES, CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS);
   }
 
   public void decorate(Resource resource, DecoratorContext context) {
@@ -55,6 +56,10 @@ public final class NewCoverageAggregator implements Decorator {
       aggregate(context, CoreMetrics.NEW_UNCOVERED_LINES, maxPeriods);
       aggregate(context, CoreMetrics.NEW_CONDITIONS_TO_COVER, maxPeriods);
       aggregate(context, CoreMetrics.NEW_UNCOVERED_CONDITIONS, maxPeriods);
+      aggregate(context, CoreMetrics.NEW_IT_LINES_TO_COVER, maxPeriods);
+      aggregate(context, CoreMetrics.NEW_IT_UNCOVERED_LINES, maxPeriods);
+      aggregate(context, CoreMetrics.NEW_IT_CONDITIONS_TO_COVER, maxPeriods);
+      aggregate(context, CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS, maxPeriods);
     }
   }
 
index d44ffd056e1c9646a81da437aa54da48b72ed6f9..59929b27d886c71be6bb2c44ca34ff51d076065a 100644 (file)
  */
 package org.sonar.plugins.core.timemachine;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import org.apache.commons.lang.ObjectUtils;
-import org.sonar.api.batch.*;
 import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.resources.Scopes;
-import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.batch.components.PastSnapshot;
 import org.sonar.batch.components.TimeMachineConfiguration;
-import org.sonar.core.NotDryRun;
 
-import java.util.Arrays;
-import java.util.Date;
 import java.util.List;
-import java.util.Map;
 
-/**
- * @since 2.7
- */
-@NotDryRun
-@DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE)
-public final class NewCoverageFileAnalyzer implements Decorator {
-
-  private List<PeriodStruct> structs;
+public class NewCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer {
 
   public NewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration) {
-    structs = Lists.newArrayList();
-    for (PastSnapshot pastSnapshot : timeMachineConfiguration.getProjectPastSnapshots()) {
-      structs.add(new PeriodStruct(pastSnapshot));
-    }
+    super(timeMachineConfiguration);
   }
 
   NewCoverageFileAnalyzer(List<PeriodStruct> structs) {
-    this.structs = structs;
-  }
-
-  public boolean shouldExecuteOnProject(Project project) {
-    return project.isLatestAnalysis() && !structs.isEmpty();
-  }
-
-  private boolean shouldDecorate(Resource resource) {
-    return Scopes.isFile(resource) && !Qualifiers.UNIT_TEST_FILE.equals(resource.getQualifier());
+    super(structs);
   }
 
-  @DependsUpon
-  public List<Metric> dependsOnMetrics() {
-    return Arrays.asList(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE, CoreMetrics.COVERAGE_LINE_HITS_DATA,
-        CoreMetrics.CONDITIONS_BY_LINE, CoreMetrics.COVERED_CONDITIONS_BY_LINE);
+  @Override
+  public Metric getCoverageLineHitsDataMetric() {
+    return CoreMetrics.COVERAGE_LINE_HITS_DATA;
   }
 
-  @DependedUpon
-  public List<Metric> generatesNewCoverageMetrics() {
-    return Arrays.asList(CoreMetrics.NEW_LINES_TO_COVER, CoreMetrics.NEW_UNCOVERED_LINES,
-        CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS);
+  @Override
+  public Metric getConditionsByLineMetric() {
+    return CoreMetrics.CONDITIONS_BY_LINE;
   }
 
-  public void decorate(Resource resource, DecoratorContext context) {
-    if (shouldDecorate(resource)) {
-      doDecorate(context);
-    }
+  @Override
+  public Metric getCoveredConditionsByLineMetric() {
+    return CoreMetrics.COVERED_CONDITIONS_BY_LINE;
   }
 
-  void doDecorate(DecoratorContext context) {
-    if (parse(context)) {
-      compute(context);
-    }
+  @Override
+  public Metric getNewLinesToCoverMetric() {
+    return CoreMetrics.NEW_LINES_TO_COVER;
   }
 
-  private boolean parse(DecoratorContext context) {
-    Measure lastCommits = context.getMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE);
-    Measure hitsByLineMeasure = context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA);
-
-    if (lastCommits != null && lastCommits.hasData() && hitsByLineMeasure != null && hitsByLineMeasure.hasData()) {
-      Map<Integer, Date> datesByLine = KeyValueFormat.parseIntDateTime(lastCommits.getData());
-      Map<Integer, Integer> hitsByLine = parseCountByLine(hitsByLineMeasure);
-      Map<Integer, Integer> conditionsByLine = parseCountByLine(context.getMeasure(CoreMetrics.CONDITIONS_BY_LINE));
-      Map<Integer, Integer> coveredConditionsByLine = parseCountByLine(context.getMeasure(CoreMetrics.COVERED_CONDITIONS_BY_LINE));
-
-      reset();
-
-      for (Map.Entry<Integer, Integer> entry : hitsByLine.entrySet()) {
-        int lineId = entry.getKey();
-        int hits = entry.getValue();
-        int conditions = (Integer)ObjectUtils.defaultIfNull(conditionsByLine.get(lineId), 0);
-        int coveredConditions = (Integer)ObjectUtils.defaultIfNull(coveredConditionsByLine.get(lineId), 0);
-        Date date = datesByLine.get(lineId);
-        for (PeriodStruct struct : structs) {
-          struct.analyze(date, hits, conditions, coveredConditions);
-        }
-      }
-
-      return true;
-    }
-    return false;
+  @Override
+  public Metric getNewUncoveredLinesMetric() {
+    return CoreMetrics.NEW_UNCOVERED_LINES;
   }
 
-  private void reset() {
-    for (PeriodStruct struct : structs) {
-      struct.reset();
-    }
+  @Override
+  public Metric getNewConditionsToCoverMetric() {
+    return CoreMetrics.NEW_CONDITIONS_TO_COVER;
   }
 
-  private void compute(DecoratorContext context) {
-    Measure newLines = new Measure(CoreMetrics.NEW_LINES_TO_COVER);
-    Measure newUncoveredLines = new Measure(CoreMetrics.NEW_UNCOVERED_LINES);
-    Measure newConditions = new Measure(CoreMetrics.NEW_CONDITIONS_TO_COVER);
-    Measure newUncoveredConditions = new Measure(CoreMetrics.NEW_UNCOVERED_CONDITIONS);
-
-    for (PeriodStruct struct : structs) {
-      newLines.setVariation(struct.index, (double)struct.newLines);
-      newUncoveredLines.setVariation(struct.index, (double) (struct.newLines - struct.newCoveredLines));
-      newConditions.setVariation(struct.index, (double)struct.newConditions);
-      newUncoveredConditions.setVariation(struct.index, (double)struct.newConditions-struct.newCoveredConditions);
-    }
-
-    context.saveMeasure(newLines);
-    context.saveMeasure(newUncoveredLines);
-    context.saveMeasure(newConditions);
-    context.saveMeasure(newUncoveredConditions);
-  }
-
-  private Map<Integer, Integer> parseCountByLine(Measure measure) {
-    if (measure != null && measure.hasData()) {
-      return KeyValueFormat.parseIntInt(measure.getData());
-    }
-    return Maps.newHashMap();
-  }
-
-  public static final class PeriodStruct {
-    int index;
-    Date date;
-    int newLines = 0, newCoveredLines = 0, newConditions = 0, newCoveredConditions = 0;
-
-    PeriodStruct(PastSnapshot pastSnapshot) {
-      this.index = pastSnapshot.getIndex();
-      this.date = pastSnapshot.getTargetDate();
-    }
-
-    PeriodStruct(int index, Date date) {
-      this.index = index;
-      this.date = date;
-    }
-
-    void reset() {
-      newLines = 0;
-      newCoveredLines = 0;
-      newConditions = 0;
-      newCoveredConditions = 0;
-    }
-
-    void analyze(Date lineDate, int hits, int conditions, int coveredConditions) {
-      if (lineDate == null) {
-        // TODO warning
-
-      } else if (date == null || lineDate.after(date)) {
-        // TODO test if string comparison is faster or not
-        addLine(hits > 0);
-        addConditions(conditions, coveredConditions);
-      }
-    }
-
-    void addLine(boolean covered) {
-      newLines += 1;
-      if (covered) {
-        newCoveredLines += 1;
-      }
-    }
-
-    void addConditions(int count, int countCovered) {
-      newConditions += count;
-      if (count > 0) {
-        newCoveredConditions += countCovered;
-      }
-    }
+  @Override
+  public Metric getNewUncoveredConditionsMetric() {
+    return CoreMetrics.NEW_UNCOVERED_CONDITIONS;
   }
 }
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java
new file mode 100644 (file)
index 0000000..d3492f7
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 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.timemachine;
+
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Metric;
+import org.sonar.batch.components.TimeMachineConfiguration;
+
+public class NewItCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer {
+
+  public NewItCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration) {
+    super(timeMachineConfiguration);
+  }
+
+  @Override
+  public Metric getCoverageLineHitsDataMetric() {
+    return CoreMetrics.IT_COVERAGE_LINE_HITS_DATA;
+  }
+
+  @Override
+  public Metric getConditionsByLineMetric() {
+    return CoreMetrics.IT_CONDITIONS_BY_LINE;
+  }
+
+  @Override
+  public Metric getCoveredConditionsByLineMetric() {
+    return CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE;
+  }
+
+  @Override
+  public Metric getNewLinesToCoverMetric() {
+    return CoreMetrics.NEW_IT_LINES_TO_COVER;
+  }
+
+  @Override
+  public Metric getNewUncoveredLinesMetric() {
+    return CoreMetrics.NEW_IT_UNCOVERED_LINES;
+  }
+
+  @Override
+  public Metric getNewConditionsToCoverMetric() {
+    return CoreMetrics.NEW_IT_CONDITIONS_TO_COVER;
+  }
+
+  @Override
+  public Metric getNewUncoveredConditionsMetric() {
+    return CoreMetrics.NEW_IT_UNCOVERED_CONDITIONS;
+  }
+}
index 3eb6a0f27ed3c886c2d677d79173f20287092abf..85d1eb5b6c2dd44abaafd831d22530a1681c22d2 100644 (file)
@@ -44,7 +44,7 @@ public class NewCoverageFileAnalyzerTest {
     when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA))
         .thenReturn(new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "1=10"));
 
-    NewCoverageFileAnalyzer decorator = newDecorator();
+    AbstractNewCoverageFileAnalyzer decorator = newDecorator();
     decorator.doDecorate(context);
     verify(context, never()).saveMeasure((Measure) anyObject());
   }
@@ -55,7 +55,7 @@ public class NewCoverageFileAnalyzerTest {
     when(context.getMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE))
         .thenReturn(new Measure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE, "10=2008-05-18T00:00:00+0000"));
 
-    NewCoverageFileAnalyzer decorator = newDecorator();
+    AbstractNewCoverageFileAnalyzer decorator = newDecorator();
     decorator.doDecorate(context);
 
     verify(context, never()).saveMeasure((Measure) anyObject());
@@ -69,7 +69,7 @@ public class NewCoverageFileAnalyzerTest {
     when(context.getMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE)).thenReturn(
         new Measure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE, "10=2007-01-15T00:00:00+0000;11=2011-01-01T00:00:00+0000"));
 
-    NewCoverageFileAnalyzer decorator = newDecorator();
+    AbstractNewCoverageFileAnalyzer decorator = newDecorator();
     decorator.doDecorate(context);
 
     // line 11 has been updated after date1 (2009-12-25). This line is covered.
@@ -101,7 +101,7 @@ public class NewCoverageFileAnalyzerTest {
     when(context.getMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE)).thenReturn(
         new Measure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE, "10=2007-01-15T00:00:00+0000;11=2011-01-01T00:00:00+0000"));
 
-    NewCoverageFileAnalyzer decorator = newDecorator();
+    AbstractNewCoverageFileAnalyzer decorator = newDecorator();
     decorator.doDecorate(context);
 
     // line 11 has been updated after date1 (2009-12-25). This line has 1 covered condition amongst 4
@@ -133,7 +133,7 @@ public class NewCoverageFileAnalyzerTest {
     when(context.getMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE)).thenReturn(
         new Measure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE, "10=2007-01-15T00:00:00+0000;11=2011-01-01T00:00:00+0000"));
 
-    NewCoverageFileAnalyzer decorator = newDecorator();
+    AbstractNewCoverageFileAnalyzer decorator = newDecorator();
     decorator.doDecorate(context);
 
     // line 11 has been updated after date1 (2009-12-25) but it has no conditions
@@ -169,10 +169,10 @@ public class NewCoverageFileAnalyzerTest {
     }
   }
 
-  private NewCoverageFileAnalyzer newDecorator() throws ParseException {
-    List<NewCoverageFileAnalyzer.PeriodStruct> structs = Arrays.asList(
-        new NewCoverageFileAnalyzer.PeriodStruct(1, newDate("2009-12-25")),
-        new NewCoverageFileAnalyzer.PeriodStruct(3, newDate("2011-02-18")));
+  private AbstractNewCoverageFileAnalyzer newDecorator() throws ParseException {
+    List<AbstractNewCoverageFileAnalyzer.PeriodStruct> structs = Arrays.asList(
+        new AbstractNewCoverageFileAnalyzer.PeriodStruct(1, newDate("2009-12-25")),
+        new AbstractNewCoverageFileAnalyzer.PeriodStruct(3, newDate("2011-02-18")));
     return new NewCoverageFileAnalyzer(structs);
   }
 
index 18be484753717b029be239b1e21b73d9eb2ceb2f..aee588e9d476735ce815e295f0c7a1dee4d442e4 100644 (file)
@@ -102,9 +102,6 @@ public class JaCoCoPlugin extends SonarPlugin {
 
         // Integration tests
         JaCoCoItSensor.class,
-        ItCoverageWidget.class,
-        ItCoverageDecorator.class,
-        ItLineCoverageDecorator.class,
-        ItBranchCoverageDecorator.class);
+        ItCoverageWidget.class);
   }
 }
index 283b3cd524b6bf29bbac5be0b54d3e9c35187af0..0a60f2e9a897e1f13078593014af1a2f15489c70 100644 (file)
@@ -593,11 +593,11 @@ violations_drilldown.no_violations=No violations
 
 #------------------------------------------------------------------------------
 #
-# DUPLICATION TAB
+# DUPLICATION VIEWER
 #
 #------------------------------------------------------------------------------
 
-duplications.no_duplicated_block=No duplicated block.
+duplications.no_duplicated_block=No duplicated blocks.
 duplications.blocks=Blocks
 duplications.number_of_lines=Nb Lines
 duplications.from_line=From line
@@ -609,11 +609,12 @@ duplications.collapse=Collapse
 
 #------------------------------------------------------------------------------
 #
-# COVERAGE TAB
+# COVERAGE VIEWER
 #
 #------------------------------------------------------------------------------
-coverage_tab.unit_tests=Unit Tests
-coverage_tab.integration_tests=Integration Tests
+coverage_viewer.on_new_code=On new code
+coverage_viewer.unit_tests=Unit Tests
+coverage_viewer.integration_tests=Integration Tests
 
 #------------------------------------------------------------------------------
 #
@@ -1119,35 +1120,35 @@ metric.covered_conditions_by_line.description=Covered branches by line
 #
 #--------------------------------------------------------------------------------------------------------------------
 
-metric.it_coverage.name=Coverage
-metric.it_coverage.description=Coverage by unit tests
+metric.it_coverage.name=IT Coverage
+metric.it_coverage.description=Coverage by Integration Tests
 
-metric.it_lines_to_cover.name=Lines to cover
-metric.it_lines_to_cover.description=Lines to cover
+metric.it_lines_to_cover.name=Lines to cover by IT
+metric.it_lines_to_cover.description=Lines to cover by Integration Tests
 
-metric.it_uncovered_lines.name=Uncovered lines
-metric.it_uncovered_lines.description=Uncovered lines
+metric.it_uncovered_lines.name=Uncovered lines by IT
+metric.it_uncovered_lines.description=Uncovered lines by Integration Tests
 
-metric.it_line_coverage.name=Line coverage
-metric.it_line_coverage.description=Line coverage
+metric.it_line_coverage.name=Line coverage by IT
+metric.it_line_coverage.description=Line coverage by Integration Tests
 
-metric.it_coverage_line_hits_data.name=Coverage hits by line
-metric.it_coverage_line_hits_data.description=Coverage hits by line
+metric.it_coverage_line_hits_data.name=IT Coverage hits by line
+metric.it_coverage_line_hits_data.description=Coverage hits by line by Integration Tests
 
-metric.it_conditions_to_cover.name=Branches to cover
-metric.it_conditions_to_cover.description=Branches to cover
+metric.it_conditions_to_cover.name=Branches to cover by IT
+metric.it_conditions_to_cover.description=Branches to cover by Integration Tests
 
-metric.it_uncovered_conditions.name=Uncovered branches
-metric.it_uncovered_conditions.description=Uncovered branches
+metric.it_uncovered_conditions.name=Uncovered branches by IT
+metric.it_uncovered_conditions.description=Uncovered branches by Integration Tests
 
-metric.it_branch_coverage.name=Branch coverage
-metric.it_branch_coverage.description=Branch coverage
+metric.it_branch_coverage.name=Branch coverage by IT
+metric.it_branch_coverage.description=Branch coverage by Integration Tests
 
-metric.it_conditions_by_line.name=Branches by line
-metric.it_conditions_by_line.description=Branches by line
+metric.it_conditions_by_line.name=IT Branches by line
+metric.it_conditions_by_line.description=IT Branches by line
 
-metric.it_covered_conditions_by_line.name=Covered branches by line
-metric.it_covered_conditions_by_line.description=Covered branches by line
+metric.it_covered_conditions_by_line.name=IT Covered branches by line
+metric.it_covered_conditions_by_line.description=IT Covered branches by line
 
 #--------------------------------------------------------------------------------------------------------------------
 #
index e391d3ad130e21091dc44042830d10fcfcbf4b7a..5f8490a385812a115dc18cfcaf3a97be43805465 100644 (file)
@@ -27,7 +27,7 @@ import java.util.Properties;
 public class CustomHibernateConnectionProvider extends InjectedDataSourceConnectionProvider {
 
   static DataSource datasource;
-
+  
   @Override
   public void configure(Properties props) {
     setDataSource(datasource);
index 555d753440a6ffa3ba0cd235257b29852d5f7e21..c498bc00ca9a195f7817f55f2ce4fe7c1102eab5 100644 (file)
@@ -618,9 +618,20 @@ public final class CoreMetrics {
     .setBestValue(100.0)
     .create();
 
+public static final String NEW_IT_COVERAGE_KEY = "new_it_coverage";
+  public static final Metric NEW_IT_COVERAGE = new Metric.Builder(NEW_IT_COVERAGE_KEY, "New IT coverage", Metric.ValueType.PERCENT)
+    .setDescription("Integration Tests Coverage of new/changed code")
+    .setDirection(Metric.DIRECTION_BETTER)
+    .setQualitative(true)
+    .setDomain(DOMAIN_INTEGRATION_TESTS)
+    .setWorstValue(0.0)
+    .setBestValue(100.0)
+    .create();
+
+
   public static final String IT_LINES_TO_COVER_KEY = "it_lines_to_cover";
   public static final Metric IT_LINES_TO_COVER = new Metric.Builder(IT_LINES_TO_COVER_KEY, "IT Lines to cover", Metric.ValueType.INT)
-    .setDescription("IT lines to cover")
+    .setDescription("Lines to cover by Integration Tests")
     .setDirection(Metric.DIRECTION_BETTER)
     .setDomain(DOMAIN_INTEGRATION_TESTS)
     .setQualitative(false)
@@ -628,6 +639,16 @@ public final class CoreMetrics {
     .setHidden(true)
     .create();
 
+public static final String NEW_IT_LINES_TO_COVER_KEY = "new_it_lines_to_cover";
+  public static final Metric NEW_IT_LINES_TO_COVER = new Metric.Builder(NEW_IT_LINES_TO_COVER_KEY, "New lines to cover by IT", Metric.ValueType.INT)
+    .setDescription("New lines to cover by Integration Tests")
+    .setDirection(Metric.DIRECTION_WORST)
+    .setQualitative(false)
+    .setDomain(DOMAIN_INTEGRATION_TESTS)
+    .setFormula(new SumChildValuesFormula(false))
+    .create();
+
+
   public static final String IT_UNCOVERED_LINES_KEY = "it_uncovered_lines";
   public static final Metric IT_UNCOVERED_LINES = new Metric.Builder(IT_UNCOVERED_LINES_KEY, "IT Uncovered lines", Metric.ValueType.INT)
     .setDescription("IT uncovered lines")
@@ -637,6 +658,15 @@ public final class CoreMetrics {
     .setFormula(new SumChildValuesFormula(false))
     .create();
 
+  public static final String NEW_IT_UNCOVERED_LINES_KEY = "new_it_uncovered_lines";
+  public static final Metric NEW_IT_UNCOVERED_LINES = new Metric.Builder(NEW_IT_UNCOVERED_LINES_KEY, "New uncovered lines by IT", Metric.ValueType.INT)
+    .setDescription("New uncovered lines by Integration Tests")
+    .setDirection(Metric.DIRECTION_WORST)
+    .setDomain(DOMAIN_INTEGRATION_TESTS)
+    .setFormula(new SumChildValuesFormula(false))
+    .setBestValue(0.0)
+    .create();
+
   public static final String IT_LINE_COVERAGE_KEY = "it_line_coverage";
   public static final Metric IT_LINE_COVERAGE = new Metric.Builder(IT_LINE_COVERAGE_KEY, "IT Line coverage", Metric.ValueType.PERCENT)
     .setDescription("IT line coverage")
@@ -645,6 +675,16 @@ public final class CoreMetrics {
     .setDomain(DOMAIN_INTEGRATION_TESTS)
     .create();
 
+  public static final String NEW_IT_LINE_COVERAGE_KEY = "new_it_line_coverage";
+  public static final Metric NEW_IT_LINE_COVERAGE = new Metric.Builder(NEW_IT_LINE_COVERAGE_KEY, "New line coverage by IT", Metric.ValueType.PERCENT)
+    .setDescription("Line Coverage by Integration Tests of added/changed code")
+    .setDirection(Metric.DIRECTION_BETTER)
+    .setQualitative(true)
+    .setWorstValue(0.0)
+    .setBestValue(100.0)
+    .setDomain(DOMAIN_INTEGRATION_TESTS)
+    .create();
+
   public static final String IT_COVERAGE_LINE_HITS_DATA_KEY = "it_coverage_line_hits_data";
   public static final Metric IT_COVERAGE_LINE_HITS_DATA = new Metric.Builder(IT_COVERAGE_LINE_HITS_DATA_KEY, "IT Coverage hits data", Metric.ValueType.DATA)
     .setDescription("IT Code coverage line hits data")
@@ -663,6 +703,13 @@ public final class CoreMetrics {
     .setHidden(true)
     .create();
 
+  public static final String NEW_IT_CONDITIONS_TO_COVER_KEY = "new_it_conditions_to_cover";
+  public static final Metric NEW_IT_CONDITIONS_TO_COVER = new Metric.Builder(NEW_IT_CONDITIONS_TO_COVER_KEY, "New conditions to cover by IT", Metric.ValueType.INT)
+    .setDescription("New conditions to cover by Integration Tests")
+    .setDomain(DOMAIN_INTEGRATION_TESTS)
+    .setFormula(new SumChildValuesFormula(false))
+    .create();
+
   public static final String IT_UNCOVERED_CONDITIONS_KEY = "it_uncovered_conditions";
   public static final Metric IT_UNCOVERED_CONDITIONS = new Metric.Builder(IT_UNCOVERED_CONDITIONS_KEY, "IT Uncovered branches", Metric.ValueType.INT)
     .setDescription("IT Uncovered conditions")
@@ -671,6 +718,15 @@ public final class CoreMetrics {
     .setFormula(new SumChildValuesFormula(false))
     .create();
 
+  public static final String NEW_IT_UNCOVERED_CONDITIONS_KEY = "new_it_uncovered_conditions";
+  public static final Metric NEW_IT_UNCOVERED_CONDITIONS = new Metric.Builder(NEW_IT_UNCOVERED_CONDITIONS_KEY, "New uncovered conditions by IT", Metric.ValueType.INT)
+    .setDescription("New uncovered conditions by Integration Tests")
+    .setDirection(Metric.DIRECTION_WORST)
+    .setDomain(DOMAIN_INTEGRATION_TESTS)
+    .setFormula(new SumChildValuesFormula(false))
+    .setBestValue(0.0)
+    .create();
+
   public static final String IT_BRANCH_COVERAGE_KEY = "it_branch_coverage";
   public static final Metric IT_BRANCH_COVERAGE = new Metric.Builder(IT_BRANCH_COVERAGE_KEY, "IT Branch coverage", Metric.ValueType.PERCENT)
     .setDescription("IT Branch coverage")
@@ -681,6 +737,16 @@ public final class CoreMetrics {
     .setBestValue(100.0)
     .create();
 
+  public static final String NEW_IT_BRANCH_COVERAGE_KEY = "new_it_branch_coverage";
+  public static final Metric NEW_IT_BRANCH_COVERAGE = new Metric.Builder(NEW_IT_BRANCH_COVERAGE_KEY, "New branch coverage by IT", Metric.ValueType.PERCENT)
+    .setDescription("Branch coverage by Integration Tests of new/changed code")
+    .setDirection(Metric.DIRECTION_BETTER)
+    .setQualitative(true)
+    .setDomain(DOMAIN_INTEGRATION_TESTS)
+    .setWorstValue(0.0)
+    .setBestValue(100.0)
+    .create();
+
   public static final String IT_CONDITIONS_BY_LINE_KEY = "it_conditions_by_line";
 
   public static final Metric IT_CONDITIONS_BY_LINE = new Metric.Builder(IT_CONDITIONS_BY_LINE_KEY, "IT Branches by line", Metric.ValueType.DATA)
index 2b753e44d7a58b114fb3073a4ddc1f84137a95c3..d977d296130cd6580175bba071d6300970dc2f8c 100644 (file)
@@ -167,21 +167,25 @@ class ResourceController < ApplicationController
       @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)
+          '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)
         @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
+      elsif ('uncovered_lines'==@coverage_filter || 'new_uncovered_lines'==@coverage_filter ||
+            'it_uncovered_lines'==@coverage_filter || 'new_it_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 ||
+      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
+            'it_conditions_to_cover'==@coverage_filter || 'it_branch_coverage'==@coverage_filter ||
+            'new_it_conditions_to_cover' == @coverage_filter || 'new_it_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
+      elsif ('uncovered_conditions' == @coverage_filter || 'new_uncovered_conditions' == @coverage_filter ||
+            'it_uncovered_conditions'==@coverage_filter || 'new_it_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
index 1745af879e99d1a81e00778575154fc7a224e4d2..de128aa09bb4b6c6dee0628f3a6e9cb7753a8529 100644 (file)
@@ -542,9 +542,8 @@ module ApplicationHelper
         end
         html="<span class='#{css_class}'>#{formatted_val}</span>"
       end
-    else
-      html = options[:default].to_s
     end
+    html = options[:default].to_s if html.nil? && options[:default]
     html
   end
 end
index abcf4e4c39763f4b23c69524912d920c77460558..c3b9e18b93586d468429767c6b0470d24c1c38b3 100644 (file)
@@ -1,15 +1,15 @@
 <div id="coverage_header" class="tab_header">
-    <% if @period && measure('new_coverage') %>
-      <p>On new code:</p>
+    <% if @period && (measure('new_coverage') || measure('new_it_coverage')) %>
+      <p><%= message('coverage_viewer.on_new_code') -%> :</p>
       <table>
         <tr>
-          <td class="big" rowspan="2"><%= format_variation('new_coverage', :period => @period, :style => 'none') -%></td>
+          <td class="big" rowspan="2"><%= format_variation('new_coverage', :period => @period, :default => '-', :style => 'none') -%></td>
 
           <td class="sep"> </td>
 
           <% if m=measure('new_line_coverage') %>
             <td class="name"><%= Metric.name_for('line_coverage') -%>:</td>
-            <td class="value"><%= format_variation(m, :period => @period, :style => 'none') -%></td>
+            <td class="value"><%= format_variation(m, :period => @period, :default => '-', :style => 'none') -%></td>
           <% else %>
             <td colspan="2"></td>
           <% end %>
@@ -17,7 +17,7 @@
           <td class="sep"> </td>
           <% if m=measure('new_branch_coverage') %>
             <td class="name"><%= Metric.name_for('branch_coverage') -%>:</td>
-            <td class="value"><%= format_variation(m, :period => @period, :style => 'none') -%></td>
+            <td class="value"><%= format_variation(m, :period => @period, :default => '-', :style => 'none') -%></td>
           <% else %>
             <td colspan="2"></td>
           <% end %>
             <td colspan="2"></td>
           <% end %>
         </tr>
+      <% if measure('new_it_coverage') %>
+        <tr>
+          <td colspan="7"><br/><%= message('coverage_viewer.integration_tests') -%></td>
+        </tr>
+        <tr>
+          <td class="big" rowspan="2"><%= format_variation('new_it_coverage', :period => @period, :default => '-', :style => 'none') -%></td>
+
+          <td class="sep"> </td>
+
+          <% if m=measure('new_it_line_coverage') %>
+            <td class="name"><%= Metric.name_for('it_line_coverage') -%>:</td>
+            <td class="value"><%= format_variation(m, :period => @period, :default => '-', :style => 'none') -%></td>
+          <% else %>
+            <td colspan="2"></td>
+          <% end %>
+
+          <td class="sep"> </td>
+          <% if m=measure('new_it_branch_coverage') %>
+            <td class="name"><%= Metric.name_for('it_branch_coverage') -%>:</td>
+            <td class="value"><%= format_variation(m, :period => @period, :default => '-', :style => 'none') -%></td>
+          <% else %>
+            <td colspan="2"></td>
+          <% end %>
+        </tr>
+        <tr>
+          <td class="sep"> </td>
+          <% if m=measure('new_it_uncovered_lines') %>
+            <td class="name"><%= Metric.name_for('it_uncovered_lines') -%>:</td>
+            <td class="value"><%= format_variation(m, :period => @period, :style => 'none') -%>/<%= format_variation('new_it_lines_to_cover', :period => @period, :style => 'none') -%></td>
+          <% else %>
+            <td colspan="2"></td>
+          <% end %>
+
+          <td class="sep"> </td>
+          <% if m=measure('new_it_uncovered_conditions') %>
+            <td class="name"><%= Metric.name_for('it_uncovered_conditions') -%>: </td>
+            <td class="value"><%= format_variation(m, :period => @period, :style => 'none') -%>/<%= format_variation('new_it_conditions_to_cover', :period => @period, :style => 'none') -%></td>
+          <% else %>
+            <td colspan="2"></td>
+          <% end %>
+        </tr>
+      <% end %>
       </table>
     <% else %>
       <table>
         <% if @display_it_coverage %>
           <tr>
-            <td colspan="8"><%= message('coverage_tab.unit_tests') -%></td>
-            <td colspan="7"><%= message('coverage_tab.integration_tests') -%></td>
+            <td colspan="7"><%= message('coverage_viewer.unit_tests') -%></td>
           </tr>
         <% end %>
         <tr>
           <%= render :partial => 'measure', :locals => {:measure => measure('line_coverage'), :title => Metric.name_for('line_coverage')} -%>
           <td class="sep"> </td>
           <%= render :partial => 'measure', :locals => {:measure => measure('branch_coverage'), :title => Metric.name_for('branch_coverage')} -%>
+        </tr>
+        <tr>
           <td class="sep"> </td>
+          <%= render :partial => 'measure', :locals => {:measure => measure('uncovered_lines'), :title => Metric.name_for('uncovered_lines'), :ratio => measure('lines_to_cover')} -%>
+          <td class="sep"> </td>
+          <%= render :partial => 'measure', :locals => {:measure => measure('uncovered_conditions'), :title => Metric.name_for('uncovered_conditions'), :ratio => measure('conditions_to_cover')} -%>
+        </tr>
 
-          <% if @display_it_coverage %>
+      <% if @display_it_coverage %>
+        <tr>
+          <td colspan="7"><br/><%= message('coverage_viewer.integration_tests') -%></td>
+        </tr>
+        <tr>
           <td class="big" rowspan="2"><%= format_measure('it_coverage', :default => '-') -%></td>
           <td class="sep"> </td>
           <%= render :partial => 'measure', :locals => {:measure => measure('it_line_coverage'), :title => Metric.name_for('it_line_coverage')} -%>
           <td class="sep"> </td>
           <%= render :partial => 'measure', :locals => {:measure => measure('it_branch_coverage'), :title => Metric.name_for('it_branch_coverage')} -%>
-          <% end %>
         </tr>
         <tr>
-          <td class="sep"> </td>
-          <%= render :partial => 'measure', :locals => {:measure => measure('uncovered_lines'), :title => Metric.name_for('uncovered_lines'), :ratio => measure('lines_to_cover')} -%>
-          <td class="sep"> </td>
-          <%= render :partial => 'measure', :locals => {:measure => measure('uncovered_conditions'), :title => Metric.name_for('uncovered_conditions'), :ratio => measure('conditions_to_cover')} -%>
-          <td class="sep"> </td>
-          <% if @display_it_coverage %>
           <td class="sep"> </td>
           <%= render :partial => 'measure', :locals => {:measure => measure('it_uncovered_lines'), :title => Metric.name_for('it_uncovered_lines'), :ratio => measure('it_lines_to_cover')} -%>
           <td class="sep"> </td>
           <%= render :partial => 'measure', :locals => {:measure => measure('it_uncovered_conditions'), :title => Metric.name_for('it_uncovered_conditions'), :ratio => measure('it_conditions_to_cover')} -%>
-          <% end %>
         </tr>
+      <% end %>
       </table>
     <% end %>
-  
+
   <%= render :partial => 'options' -%>
 </div>
 
index d625f26280d60e37d3efac1c3fc5b5f5ca30475d..221c1b3680f1415d13a8899ee6d0de3b0f69cd22 100644 (file)
         <% if @display_coverage %>
         <td class="<%= 'first' if first -%>">
           <select id="coverage_filter" name="coverage_filter" onchange="applyOptions()">
-            <optgroup label="<%= h message('coverage_tab.unit_tests') -%>">
+            <optgroup label="<%= h message('coverage_viewer.unit_tests') -%>">
               <option value="lines_to_cover" <%= 'selected' if @coverage_filter=='lines_to_cover' -%>><%= Metric.name_for('lines_to_cover') -%></option>
               <option value="uncovered_lines" <%= 'selected' if @coverage_filter=='uncovered_lines' -%>><%= Metric.name_for('uncovered_lines') -%></option>
               <option value="conditions_to_cover" <%= 'selected' if @coverage_filter=='conditions_to_cover' -%>><%= Metric.name_for('conditions_to_cover') -%></option>
               <option value="uncovered_conditions" <%= 'selected' if @coverage_filter=='uncovered_conditions' -%>><%= Metric.name_for('uncovered_conditions') -%></option>
             </optgroup>
             <% if @display_it_coverage %>
-            <optgroup label="<%= h message('coverage_tab.integration_tests') -%>">
+            <optgroup label="<%= h message('coverage_viewer.integration_tests') -%>">
               <option value="it_lines_to_cover" <%= 'selected' if @coverage_filter=='it_lines_to_cover' -%>><%= Metric.name_for('it_lines_to_cover') -%></option>
               <option value="it_uncovered_lines" <%= 'selected' if @coverage_filter=='it_uncovered_lines' -%>><%= Metric.name_for('it_uncovered_lines') -%></option>
               <option value="it_conditions_to_cover" <%= 'selected' if @coverage_filter=='it_conditions_to_cover' -%>><%= Metric.name_for('it_conditions_to_cover') -%></option>