]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5772 Force coverage measure computation by default
authorJulien HENRY <julien.henry@sonarsource.com>
Thu, 19 Feb 2015 11:34:19 +0000 (12:34 +0100)
committerJulien HENRY <julien.henry@sonarsource.com>
Thu, 19 Feb 2015 11:34:45 +0000 (12:34 +0100)
21 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/AbstractCoverageDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/BranchCoverageDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItBranchCoverageDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItCoverageDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ItLineCoverageDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/LineCoverageDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/OverallBranchCoverageDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/OverallCoverageDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/OverallLineCoverageDecorator.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/BranchCoverageDecoratorTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageDecoratorTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ItBranchCoverageDecoratorTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ItCoverageDecoratorTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ItLineCoverageDecoratorTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/LineCoverageDecoratorTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/OverallBranchCoverageDecoratorTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/OverallCoverageDecoratorTest.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/OverallLineCoverageDecoratorTest.java
sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java
sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java

index c4c392084228ef5cc0642b38ed96b2087870383d..eb900b148dc190102c81fb7db2b9c68c14e75b65 100644 (file)
  */
 package org.sonar.plugins.core.sensors;
 
+import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.Decorator;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependedUpon;
+import org.sonar.api.config.Settings;
+import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
@@ -33,6 +37,30 @@ import java.util.Collection;
 
 public abstract class AbstractCoverageDecorator implements Decorator {
 
+  private Settings settings;
+
+  public AbstractCoverageDecorator(Settings settings) {
+    this.settings = settings;
+  }
+
+  protected boolean isCoverageComputationForced() {
+    return !settings.getBoolean(CoreProperties.COVERAGE_UNFORCED_KEY);
+  }
+
+  protected long getLinesToCover(DecoratorContext context) {
+    Measure linesToCover = context.getMeasure(CoreMetrics.LINES_TO_COVER);
+    if (MeasureUtils.hasValue(linesToCover)) {
+      return linesToCover.getValue().longValue();
+    } else {
+      if (isCoverageComputationForced()) {
+        // SONAR-5772 as an approximation we consider that every ncloc is a line to cover
+        return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.NCLOC), 0L);
+      } else {
+        return 0L;
+      }
+    }
+  }
+
   @Override
   public boolean shouldExecuteOnProject(Project project) {
     return true;
@@ -52,7 +80,7 @@ public abstract class AbstractCoverageDecorator implements Decorator {
   }
 
   protected boolean shouldDecorate(final Resource resource) {
-    return !ResourceUtils.isUnitTestClass(resource);
+    return !ResourceUtils.isUnitTestFile(resource);
   }
 
   private void computeMeasure(DecoratorContext context) {
index 529883fc749b5eafae679a5d8374df3c027383ca..718a039f9c4745f959c9cc3d1d1d8de8c0605691 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.plugins.core.sensors;
 
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
@@ -29,6 +30,11 @@ import org.sonar.batch.sensor.coverage.CoverageConstants;
 import java.util.Collection;
 
 public final class BranchCoverageDecorator extends AbstractCoverageDecorator {
+
+  public BranchCoverageDecorator(Settings settings) {
+    super(settings);
+  }
+
   @DependsUpon
   public Collection<Metric> dependsUponMetrics() {
     return CoverageConstants.BRANCH_COVERAGE_METRICS;
index 46b02d4e0f801ef1d55bd8ee182f1af6a181baf6..950f584206bc21a4720374f0cbedb0c556ff2466 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.plugins.core.sensors;
 
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
@@ -29,6 +30,11 @@ import org.sonar.batch.sensor.coverage.CoverageConstants;
 import java.util.Collection;
 
 public final class CoverageDecorator extends AbstractCoverageDecorator {
+
+  public CoverageDecorator(Settings settings) {
+    super(settings);
+  }
+
   @DependsUpon
   public Collection<Metric> usedMetrics() {
     return CoverageConstants.COVERAGE_METRICS;
@@ -41,10 +47,10 @@ public final class CoverageDecorator extends AbstractCoverageDecorator {
 
   @Override
   protected Long countElements(DecoratorContext context) {
-    long lines = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.LINES_TO_COVER), 0L);
+    long linesToCover = getLinesToCover(context);
     long conditions = MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.CONDITIONS_TO_COVER), 0L);
 
-    return lines + conditions;
+    return linesToCover + conditions;
   }
 
   @Override
index eb515e363a555ad9438e3f7289c3aa69244817c7..fcf30372efcdb27fbe3b2ff24a926964cca8775e 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import com.google.common.collect.ImmutableList;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
@@ -30,6 +31,10 @@ import java.util.List;
 
 public final class ItBranchCoverageDecorator extends AbstractCoverageDecorator {
 
+  public ItBranchCoverageDecorator(Settings settings) {
+    super(settings);
+  }
+
   @DependsUpon
   public List<Metric> dependsUponMetrics() {
     return ImmutableList.<Metric>of(CoreMetrics.IT_UNCOVERED_CONDITIONS, CoreMetrics.IT_CONDITIONS_TO_COVER,
index a9bd603985af3ea463db1903afea96b74f08f4ad..a32ea0f32d28e159b2fc89ac1b32edebf4b2508b 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import com.google.common.collect.ImmutableList;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
@@ -29,6 +30,11 @@ import org.sonar.api.measures.Metric;
 import java.util.Collection;
 
 public final class ItCoverageDecorator extends AbstractCoverageDecorator {
+
+  public ItCoverageDecorator(Settings settings) {
+    super(settings);
+  }
+
   @DependsUpon
   public Collection<Metric> usedMetrics() {
     return ImmutableList.<Metric>of(CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.NEW_IT_LINES_TO_COVER,
index 651d379c92eccc0f97aa9943412b73df9cde5677..1c8fa95687c0bf234e8ac2eebef8d576d32cb5ff 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import com.google.common.collect.ImmutableList;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
@@ -29,6 +30,11 @@ import org.sonar.api.measures.Metric;
 import java.util.List;
 
 public final class ItLineCoverageDecorator extends AbstractCoverageDecorator {
+
+  public ItLineCoverageDecorator(Settings settings) {
+    super(settings);
+  }
+
   @DependsUpon
   public List<Metric> dependsUponMetrics() {
     return ImmutableList.<Metric>of(CoreMetrics.IT_UNCOVERED_LINES, CoreMetrics.IT_LINES_TO_COVER, CoreMetrics.NEW_IT_UNCOVERED_LINES,
index 11ff93f0634bd86d4bf657aed145b61568473bda..fa264751ef6a12c1ec161c71d3a1bb230e226cfb 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.plugins.core.sensors;
 
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
@@ -29,6 +30,11 @@ import org.sonar.batch.sensor.coverage.CoverageConstants;
 import java.util.Collection;
 
 public final class LineCoverageDecorator extends AbstractCoverageDecorator {
+
+  public LineCoverageDecorator(Settings settings) {
+    super(settings);
+  }
+
   @DependsUpon
   public Collection<Metric> dependsUponMetrics() {
     return CoverageConstants.LINE_COVERAGE_METRICS;
@@ -41,7 +47,7 @@ public final class LineCoverageDecorator extends AbstractCoverageDecorator {
 
   @Override
   protected Long countElements(DecoratorContext context) {
-    return MeasureUtils.getValueAsLong(context.getMeasure(CoreMetrics.LINES_TO_COVER), 0L);
+    return getLinesToCover(context);
   }
 
   @Override
index 2c54896f22d2834dd558413b589aff33477ad4c2..54173d72965e141ef074aa6d42856143f85f367b 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import com.google.common.collect.ImmutableList;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
@@ -29,6 +30,11 @@ import org.sonar.api.measures.Metric;
 import java.util.List;
 
 public final class OverallBranchCoverageDecorator extends AbstractCoverageDecorator {
+
+  public OverallBranchCoverageDecorator(Settings settings) {
+    super(settings);
+  }
+
   @DependsUpon
   public List<Metric> dependsUponMetrics() {
     return ImmutableList.<Metric>of(CoreMetrics.OVERALL_UNCOVERED_CONDITIONS, CoreMetrics.OVERALL_CONDITIONS_TO_COVER,
index 998e4b3ef24fc61776fd41055069961b71ccc4ab..0efb0113e87e90d007ad751e671e10700f6f11f3 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import com.google.common.collect.ImmutableList;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
@@ -29,6 +30,11 @@ import org.sonar.api.measures.Metric;
 import java.util.Collection;
 
 public final class OverallCoverageDecorator extends AbstractCoverageDecorator {
+
+  public OverallCoverageDecorator(Settings settings) {
+    super(settings);
+  }
+
   @DependsUpon
   public Collection<Metric> usedMetrics() {
     return ImmutableList.<Metric>of(CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.NEW_OVERALL_LINES_TO_COVER,
index a3ab283cf9dd920aafcafb7aadee9b6ae87562bb..d66a8e79852930ef4a293cc224946181ed2bb7ab 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import com.google.common.collect.ImmutableList;
 import org.sonar.api.batch.DecoratorContext;
 import org.sonar.api.batch.DependsUpon;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.MeasureUtils;
 import org.sonar.api.measures.Metric;
@@ -29,6 +30,11 @@ import org.sonar.api.measures.Metric;
 import java.util.List;
 
 public final class OverallLineCoverageDecorator extends AbstractCoverageDecorator {
+
+  public OverallLineCoverageDecorator(Settings settings) {
+    super(settings);
+  }
+
   @DependsUpon
   public List<Metric> dependsUponMetrics() {
     return ImmutableList.<Metric>of(CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_LINES,
index 6c88fb9aceba543a49505270adb68ee2784f59b5..be6d69ed9edf295892bcff9f7026dfdf6c412ac6 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.resources.Project;
@@ -36,7 +37,7 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class BranchCoverageDecoratorTest {
-  private final BranchCoverageDecorator decorator = new BranchCoverageDecorator();
+  private final BranchCoverageDecorator decorator = new BranchCoverageDecorator(new Settings());
   private final Project resource = mock(Project.class);
 
   @Before
index 1db7fca5f627861f31a65366201607897be64aa1..d43e6c9aab1ea7f797ac3dbe1251ca2f74c4bb37 100644 (file)
@@ -21,7 +21,9 @@ package org.sonar.plugins.core.sensors;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.Metric;
@@ -31,20 +33,23 @@ import org.sonar.api.resources.Scopes;
 import java.util.Collection;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.anyDouble;
-import static org.mockito.Mockito.eq;
+import static org.mockito.Matchers.anyDouble;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class CoverageDecoratorTest {
-  private final CoverageDecorator decorator = new CoverageDecorator();
+  private Settings settings;
+  private CoverageDecorator decorator;
   private final Project project = mock(Project.class);
 
   @Before
   public void before() {
     when(project.getScope()).thenReturn(Scopes.PROJECT);
+    settings = new Settings();
+    decorator = new CoverageDecorator(settings);
   }
 
   @Test
@@ -52,8 +57,8 @@ public class CoverageDecoratorTest {
     Collection<Metric> metrics = decorator.usedMetrics();
 
     assertThat(metrics).containsOnly(CoreMetrics.LINES_TO_COVER, CoreMetrics.UNCOVERED_LINES, CoreMetrics.NEW_LINES_TO_COVER,
-        CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS,
-        CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS);
+      CoreMetrics.NEW_UNCOVERED_LINES, CoreMetrics.CONDITIONS_TO_COVER, CoreMetrics.UNCOVERED_CONDITIONS,
+      CoreMetrics.NEW_CONDITIONS_TO_COVER, CoreMetrics.NEW_UNCOVERED_CONDITIONS);
   }
 
   @Test
@@ -66,6 +71,28 @@ public class CoverageDecoratorTest {
     verify(context).saveMeasure(CoreMetrics.COVERAGE, 20.0);
   }
 
+  @Test
+  public void forceCoverageByDefault() {
+    DecoratorContext context = mock(DecoratorContext.class);
+    when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 100.0));
+
+    decorator.decorate(project, context);
+
+    verify(context).saveMeasure(CoreMetrics.COVERAGE, 0.0);
+  }
+
+  @Test
+  public void dontForceCoverage() {
+    settings.setProperty(CoreProperties.COVERAGE_UNFORCED_KEY, "true");
+
+    DecoratorContext context = mock(DecoratorContext.class);
+    when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 100.0));
+
+    decorator.decorate(project, context);
+
+    verify(context, never()).saveMeasure(eq(CoreMetrics.COVERAGE), anyDouble());
+  }
+
   @Test
   public void coverageCanBe0() {
     DecoratorContext context = mockContext(50, 50, 5, 5);
index 14ba49d04328a6d19204551cf516e95b83a8d1d0..aeb02f57b560e59f79d47b70a64f843f6756ea4b 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.resources.Project;
@@ -36,7 +37,7 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class ItBranchCoverageDecoratorTest {
-  private final ItBranchCoverageDecorator decorator = new ItBranchCoverageDecorator();
+  private final ItBranchCoverageDecorator decorator = new ItBranchCoverageDecorator(new Settings());
   private final Project resource = mock(Project.class);
 
   @Before
index 78cbe32cfaac50eba21f020136ec015ed8db86b5..7749271438478a8855bcc2e33867f2f5ddbdfb71 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.Metric;
@@ -39,7 +40,7 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class ItCoverageDecoratorTest {
-  private final ItCoverageDecorator decorator = new ItCoverageDecorator();
+  private final ItCoverageDecorator decorator = new ItCoverageDecorator(new Settings());
   private final Project project = mock(Project.class);
 
   @Before
@@ -52,8 +53,8 @@ public class ItCoverageDecoratorTest {
     Collection<Metric> metrics = decorator.usedMetrics();
 
     assertThat(metrics).containsOnly(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);
+      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);
   }
 
   @Test
index e88e72596ed14271a7d74d59ca77ef8ed4edc51d..cf828aee1f218ecb165ce9896be4880f8b82b8cd 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.Metric;
@@ -31,15 +32,15 @@ import org.sonar.api.resources.Scopes;
 import java.util.List;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.anyDouble;
-import static org.mockito.Mockito.eq;
+import static org.mockito.Matchers.anyDouble;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class ItLineCoverageDecoratorTest {
-  private final ItLineCoverageDecorator decorator = new ItLineCoverageDecorator();
+  private final ItLineCoverageDecorator decorator = new ItLineCoverageDecorator(new Settings());
   private final Project project = mock(Project.class);
 
   @Before
index e2956df168399962653fa6e38300df46cc353d53..0d5df65f8e4da0b196fccf72335ffa150516208a 100644 (file)
@@ -21,7 +21,9 @@ package org.sonar.plugins.core.sensors;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.resources.Project;
@@ -36,12 +38,16 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class LineCoverageDecoratorTest {
-  private final LineCoverageDecorator decorator = new LineCoverageDecorator();
+
+  private Settings settings;
+  private LineCoverageDecorator decorator;
   private final Project project = mock(Project.class);
 
   @Before
   public void before() {
     when(project.getScope()).thenReturn(Scopes.PROJECT);
+    settings = new Settings();
+    decorator = new LineCoverageDecorator(settings);
   }
 
   @Test
@@ -69,6 +75,28 @@ public class LineCoverageDecoratorTest {
     verify(context).saveMeasure(CoreMetrics.LINE_COVERAGE, 0.0);
   }
 
+  @Test
+  public void forceCoverageByDefault() {
+    DecoratorContext context = mock(DecoratorContext.class);
+    when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 100.0));
+
+    decorator.decorate(project, context);
+
+    verify(context).saveMeasure(CoreMetrics.LINE_COVERAGE, 0.0);
+  }
+
+  @Test
+  public void dontForceCoverage() {
+    settings.setProperty(CoreProperties.COVERAGE_UNFORCED_KEY, "true");
+
+    DecoratorContext context = mock(DecoratorContext.class);
+    when(context.getMeasure(CoreMetrics.NCLOC)).thenReturn(new Measure(CoreMetrics.NCLOC, 100.0));
+
+    decorator.decorate(project, context);
+
+    verify(context, never()).saveMeasure(eq(CoreMetrics.LINE_COVERAGE), anyDouble());
+  }
+
   @Test
   public void allCoveredLines() {
     DecoratorContext context = mockContext(50, 00);
index 9f18f71df70bbc4fdb13325281736ec59b44651b..6b18547f8e6419173e0d58710f4635a8dc0c337e 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.resources.Project;
@@ -36,7 +37,7 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class OverallBranchCoverageDecoratorTest {
-  private final OverallBranchCoverageDecorator decorator = new OverallBranchCoverageDecorator();
+  private final OverallBranchCoverageDecorator decorator = new OverallBranchCoverageDecorator(new Settings());
   private final Project resource = mock(Project.class);
 
   @Before
index c7c36505448fb225dce522228035167afe23fb7e..45bd2d25d4ff828cebca147cdaec7a22c6d1116f 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.Metric;
@@ -39,7 +40,7 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class OverallCoverageDecoratorTest {
-  private final OverallCoverageDecorator decorator = new OverallCoverageDecorator();
+  private final OverallCoverageDecorator decorator = new OverallCoverageDecorator(new Settings());
   private final Project project = mock(Project.class);
 
   @Before
@@ -52,8 +53,8 @@ public class OverallCoverageDecoratorTest {
     Collection<Metric> metrics = decorator.usedMetrics();
 
     assertThat(metrics).containsOnly(CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.NEW_OVERALL_LINES_TO_COVER,
-        CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_CONDITIONS_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_CONDITIONS,
-        CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS);
+      CoreMetrics.NEW_OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_CONDITIONS_TO_COVER, CoreMetrics.OVERALL_UNCOVERED_CONDITIONS,
+      CoreMetrics.NEW_OVERALL_CONDITIONS_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_CONDITIONS);
   }
 
   @Test
index 988094c23152f83489d331e8c2c15e26f3ae30bf..96a38f5f9215d2fcf9c92cd2b0bfeab9b65984e6 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.plugins.core.sensors;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.config.Settings;
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.Metric;
@@ -31,15 +32,15 @@ import org.sonar.api.resources.Scopes;
 import java.util.List;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.anyDouble;
-import static org.mockito.Mockito.eq;
+import static org.mockito.Matchers.anyDouble;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class OverallLineCoverageDecoratorTest {
-  private final OverallLineCoverageDecorator decorator = new OverallLineCoverageDecorator();
+  private final OverallLineCoverageDecorator decorator = new OverallLineCoverageDecorator(new Settings());
   private final Project project = mock(Project.class);
 
   @Before
@@ -52,7 +53,7 @@ public class OverallLineCoverageDecoratorTest {
     List<Metric> metrics = decorator.dependsUponMetrics();
 
     assertThat(metrics).containsOnly(CoreMetrics.OVERALL_UNCOVERED_LINES, CoreMetrics.OVERALL_LINES_TO_COVER, CoreMetrics.NEW_OVERALL_UNCOVERED_LINES,
-        CoreMetrics.NEW_OVERALL_LINES_TO_COVER);
+      CoreMetrics.NEW_OVERALL_LINES_TO_COVER);
   }
 
   @Test
index 33f926a08a0a3f2568308e74b9d154b9041c06c5..af34b78ce51aa8777ac8bd0ea6aa1c445b9a36d1 100644 (file)
@@ -136,6 +136,16 @@ public class CorePropertyDefinitions {
         .category(CoreProperties.CATEGORY_EXCLUSIONS)
         .subCategory(CoreProperties.SUBCATEGORY_DUPLICATIONS_EXCLUSIONS)
         .multiValues(true)
+        .build(),
+      PropertyDefinition.builder(CoreProperties.COVERAGE_UNFORCED_KEY)
+        .defaultValue("false")
+        .type(PropertyType.BOOLEAN)
+        .name("Don't force computation of test coverage")
+        .description("By default test coverage is computed for all languages even if no coverage information is provided. "
+          + "If test coverage is not applicable to your situation and you don't want to see 0% coverage on your dashboards then set this property to 'true' "
+          + "and coverage measures will only be computed when some input data are provided.")
+        .onQualifiers(Qualifiers.PROJECT)
+        .category(CoreProperties.CATEGORY_CODE_COVERAGE)
         .build()
       ));
     return defs;
index 14699e354f48b79c2b841a59b96d806b9ae422a6..5e8991762bca09746001b32f1abbca536a87a87a 100644 (file)
@@ -563,4 +563,9 @@ public interface CoreProperties {
    * @since 5.1
    */
   String IMPORT_UNKNOWN_FILES_KEY = "sonar.import_unknown_files";
+
+  /**
+   * @since 5.1
+   */
+  String COVERAGE_UNFORCED_KEY = "sonar.coverage.unforced";
 }