]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5094 Load quality gate definitions and start generating the Quality Gate Status...
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Thu, 6 Mar 2014 14:36:41 +0000 (15:36 +0100)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Fri, 7 Mar 2014 07:42:46 +0000 (08:42 +0100)
sonar-batch/pom.xml
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java
sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGate.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGateProvider.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGateVerifier.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ServerClientTest.java
sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateProviderTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java [new file with mode: 0644]

index 4d473f381496019bbf67aec034c2dbfbe639cb5e..f4b09bf2142d2598b617e973342126d04ac9e689 100644 (file)
       <groupId>org.codehaus.sonar</groupId>
       <artifactId>sonar-squid</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.codehaus.sonar</groupId>
+      <artifactId>sonar-ws-client</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
index fe75a71053dc7820ec914376d455ff4f21f395d1..459096a3aa6f3c6d185188e5b8c521fc27a8b2d0 100644 (file)
@@ -31,6 +31,7 @@ import org.sonar.api.CoreProperties;
 import org.sonar.api.utils.HttpDownloader;
 import org.sonar.api.utils.SonarException;
 import org.sonar.batch.bootstrapper.EnvironmentInformation;
+import org.sonar.wsclient.SonarClient;
 
 import javax.annotation.Nullable;
 
@@ -49,10 +50,12 @@ public class ServerClient implements BatchComponent {
 
   private BootstrapSettings settings;
   private HttpDownloader.BaseHttpDownloader downloader;
+  private SonarClient wsClient;
 
   public ServerClient(BootstrapSettings settings, EnvironmentInformation env) {
     this.settings = settings;
     this.downloader = new HttpDownloader.BaseHttpDownloader(settings.properties(), env.toString());
+    this.wsClient = SonarClient.create(getURL());
   }
 
   public String getURL() {
@@ -93,6 +96,10 @@ public class ServerClient implements BatchComponent {
     }
   }
 
+  public SonarClient wsClient() {
+    return wsClient;
+  }
+
   private InputSupplier<InputStream> doRequest(String pathStartingWithSlash, @Nullable Integer timeoutMillis) {
     Preconditions.checkArgument(pathStartingWithSlash.startsWith("/"), "Path must start with slash /");
     String path = StringEscapeUtils.escapeHtml(pathStartingWithSlash);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGate.java b/sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGate.java
new file mode 100644 (file)
index 0000000..570d731
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.qualitygate;
+
+import com.google.common.collect.Lists;
+import org.sonar.api.BatchComponent;
+import org.sonar.wsclient.qualitygate.QualityGateCondition;
+
+import javax.annotation.Nullable;
+
+import java.util.Collection;
+
+public class QualityGate implements BatchComponent {
+
+  private final String name;
+
+  private final Collection<QualityGateCondition> conditions;
+
+  QualityGate(@Nullable String name) {
+    this.name = name;
+    this.conditions = Lists.newArrayList();
+  }
+
+  static QualityGate disabled() {
+    return new QualityGate(null);
+  }
+
+  public String name() {
+    return name;
+  }
+
+  public Collection<QualityGateCondition> conditions() {
+    return conditions;
+  }
+
+  public boolean isEnabled() {
+    return name != null;
+  }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGateProvider.java b/sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGateProvider.java
new file mode 100644 (file)
index 0000000..0a7313a
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.qualitygate;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.picocontainer.injectors.ProviderAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.MessageException;
+import org.sonar.batch.bootstrap.ServerClient;
+import org.sonar.wsclient.base.HttpException;
+import org.sonar.wsclient.qualitygate.QualityGateClient;
+import org.sonar.wsclient.qualitygate.QualityGateDetails;
+
+import java.net.HttpURLConnection;
+
+public class QualityGateProvider extends ProviderAdapter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(QualityGateProvider.class);
+
+  private static final String PROPERTY_QUALITY_GATE = "sonar.qualitygate";
+
+  public QualityGate provide(Settings settings, ServerClient client) {
+    return init(settings, client, LOG);
+  }
+
+  @VisibleForTesting
+  QualityGate init(Settings settings, ServerClient client, Logger logger) {
+    QualityGate result = QualityGate.disabled();
+    String qualityGateSetting = settings.getString(PROPERTY_QUALITY_GATE);
+    if (qualityGateSetting == null) {
+      logger.info("No quality gate is configured.");
+    } else {
+      result = load(qualityGateSetting, client.wsClient().qualityGateClient());
+    }
+    logger.info("Loaded quality gate '{}'", result.name());
+    return result;
+  }
+
+  private QualityGate load(String qualityGateSetting, QualityGateClient qualityGateClient) {
+    QualityGateDetails definitionFromServer = null;
+    try {
+      definitionFromServer = fetch(qualityGateSetting, qualityGateClient);
+    } catch (HttpException serverError) {
+      if (serverError.status() == HttpURLConnection.HTTP_NOT_FOUND) {
+        throw MessageException.of("No quality gate found with configured value '" + qualityGateSetting + "'. Please check your configuration.");
+      } else {
+        throw serverError;
+      }
+    }
+
+    QualityGate configuredGate = new QualityGate(definitionFromServer.name());
+
+    return configuredGate;
+  }
+
+  private QualityGateDetails fetch(String qualityGateSetting, QualityGateClient qualityGateClient) {
+    QualityGateDetails definitionFromServer = null;
+    try {
+      long qGateId = Long.valueOf(qualityGateSetting);
+      definitionFromServer = qualityGateClient.show(qGateId);
+    } catch(NumberFormatException configIsNameInsteadOfId) {
+      definitionFromServer = qualityGateClient.show(qualityGateSetting);
+    }
+    return definitionFromServer;
+  }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGateVerifier.java b/sonar-batch/src/main/java/org/sonar/batch/qualitygate/QualityGateVerifier.java
new file mode 100644 (file)
index 0000000..32b266e
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.qualitygate;
+
+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.Resource;
+import org.sonar.api.resources.ResourceUtils;
+
+public class QualityGateVerifier implements Decorator {
+
+  private QualityGate qualityGate;
+
+  public QualityGateVerifier(QualityGate qualityGate) {
+    this.qualityGate = qualityGate;
+  }
+
+  @DependedUpon
+  public Metric generatesQualityGateStatus() {
+    return CoreMetrics.QUALITY_GATE_STATUS;
+  }
+
+  @DependsUpon
+  public String dependsOnVariations() {
+    return DecoratorBarriers.END_OF_TIME_MACHINE;
+  }
+
+  @Override
+  public boolean shouldExecuteOnProject(Project project) {
+    return qualityGate.isEnabled();
+  }
+
+  @Override
+  public void decorate(Resource resource, DecoratorContext context) {
+    if (ResourceUtils.isRootProject(resource)) {
+      checkProjectConditions(context);
+    }
+  }
+
+  private void checkProjectConditions(DecoratorContext context) {
+    Metric.Level globalLevel = Metric.Level.OK;
+    Measure globalMeasure = new Measure(CoreMetrics.QUALITY_GATE_STATUS, globalLevel);
+    globalMeasure.setAlertStatus(globalLevel);
+    globalMeasure.setAlertText("");
+    context.saveMeasure(globalMeasure);
+  }
+
+  @Override
+  public String toString() {
+    return getClass().getSimpleName();
+  }
+}
index ed7fe786bb30276d4a34c26d6dca777a186c24d3..6bc7fdafd51f8251ec59144d7a286fe4dcdeee85 100644 (file)
  */
 package org.sonar.batch.scan;
 
-import org.sonar.batch.issue.ignore.EnforceIssuesFilter;
-import org.sonar.batch.issue.ignore.IgnoreIssuesFilter;
-import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer;
-import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer;
-import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
-import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.BatchExtension;
@@ -35,12 +28,7 @@ import org.sonar.api.batch.rule.CheckFactory;
 import org.sonar.api.platform.ComponentContainer;
 import org.sonar.api.resources.Project;
 import org.sonar.api.scan.filesystem.FileExclusions;
-import org.sonar.batch.DefaultProjectClasspath;
-import org.sonar.batch.DefaultSensorContext;
-import org.sonar.batch.DefaultTimeMachine;
-import org.sonar.batch.ProjectTree;
-import org.sonar.batch.ResourceFilters;
-import org.sonar.batch.ViolationFilters;
+import org.sonar.batch.*;
 import org.sonar.batch.bootstrap.BatchExtensionDictionnary;
 import org.sonar.batch.bootstrap.ExtensionInstaller;
 import org.sonar.batch.bootstrap.ExtensionMatcher;
@@ -52,17 +40,20 @@ import org.sonar.batch.index.ResourcePersister;
 import org.sonar.batch.issue.IssuableFactory;
 import org.sonar.batch.issue.IssueFilters;
 import org.sonar.batch.issue.ModuleIssues;
+import org.sonar.batch.issue.ignore.EnforceIssuesFilter;
+import org.sonar.batch.issue.ignore.IgnoreIssuesFilter;
+import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer;
+import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer;
+import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
+import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner;
 import org.sonar.batch.phases.PhaseExecutor;
 import org.sonar.batch.phases.PhasesTimeProfiler;
-import org.sonar.batch.rule.QProfileVerifier;
 import org.sonar.batch.qualitygate.LegacyQualityGateLoader;
 import org.sonar.batch.qualitygate.LegacyQualityGateVerifier;
-import org.sonar.batch.rule.ActiveRulesProvider;
-import org.sonar.batch.rule.ModuleQProfiles;
-import org.sonar.batch.rule.QProfileSensor;
-import org.sonar.batch.rule.RulesProfileProvider;
+import org.sonar.batch.qualitygate.QualityGateProvider;
+import org.sonar.batch.qualitygate.QualityGateVerifier;
+import org.sonar.batch.rule.*;
 import org.sonar.batch.scan.filesystem.*;
-import org.sonar.batch.scan.filesystem.FileIndexer;
 import org.sonar.batch.scan.report.JsonReport;
 import org.sonar.core.component.ScanPerspectives;
 import org.sonar.core.measure.MeasurementFilters;
@@ -134,6 +125,8 @@ public class ModuleScanContainer extends ComponentContainer {
       ResourceFilters.class,
 
       // quality gates
+      new QualityGateProvider(),
+      QualityGateVerifier.class,
       LegacyQualityGateLoader.class,
       LegacyQualityGateVerifier.class,
 
index 98889eb865fcc49bc1774cd758fcbfb19eaeef26..f9f31bcb2873d801d13c15ea5e910e219cf91505 100644 (file)
@@ -32,6 +32,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.batch.bootstrapper.EnvironmentInformation;
+import org.sonar.wsclient.SonarClient;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
@@ -136,6 +137,15 @@ public class ServerClientTest {
     newServerClient().request("/foo");
   }
 
+  @Test
+  public void should_give_access_to_ws_client() throws Exception {
+    server = new MockHttpServer();
+    server.start();
+
+    SonarClient wsClient = newServerClient().wsClient();
+    assertThat(wsClient).isNotNull();
+  }
+
   private ServerClient newServerClient() {
     when(settings.property(eq("sonar.host.url"), anyString())).thenReturn("http://localhost:" + server.getPort());
     return new ServerClient(settings, new EnvironmentInformation("Junit", "4"));
diff --git a/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateProviderTest.java
new file mode 100644 (file)
index 0000000..746c47f
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.qualitygate;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.slf4j.Logger;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.MessageException;
+import org.sonar.batch.bootstrap.ServerClient;
+import org.sonar.wsclient.SonarClient;
+import org.sonar.wsclient.base.HttpException;
+import org.sonar.wsclient.qualitygate.QualityGateClient;
+import org.sonar.wsclient.qualitygate.QualityGateDetails;
+
+import java.net.HttpURLConnection;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class QualityGateProviderTest {
+
+  @Mock
+  private Settings settings;
+
+  @Mock
+  private ServerClient client;
+
+  @Mock
+  private QualityGateClient qualityGateClient;
+
+  @Mock
+  private Logger logger;
+
+  @Before
+  public void initMocks() {
+    SonarClient wsClient = mock(SonarClient.class);
+    when(client.wsClient()).thenReturn(wsClient);
+    when(wsClient.qualityGateClient()).thenReturn(qualityGateClient);
+  }
+
+  @Test
+  public void should_load_empty_quality_gate_from_default_settings() {
+    assertThat(new QualityGateProvider().provide(settings, client).conditions()).isEmpty();
+    assertThat(new QualityGateProvider().init(settings, client, logger).isEnabled()).isFalse();
+    verify(logger).info("No quality gate is configured.");
+  }
+
+  @Test
+  public void should_load_quality_gate_using_name() {
+    String qGateName = "Sonar way";
+    when(settings.getString("sonar.qualitygate")).thenReturn(qGateName);
+    QualityGateDetails qGate = mock(QualityGateDetails.class);
+    when(qualityGateClient.show(qGateName)).thenReturn(qGate);
+    when(qGate.name()).thenReturn(qGateName);
+    QualityGate actualGate = new QualityGateProvider().init(settings, client, logger);
+    assertThat(actualGate.name()).isEqualTo(qGateName);
+    assertThat(actualGate.isEnabled()).isTrue();
+    verify(logger).info("Loaded quality gate '{}'", qGateName);
+  }
+
+  @Test
+  public void should_load_quality_gate_using_id() {
+    long qGateId = 12345L;
+    String qGateName = "Sonar way";
+    when(settings.getString("sonar.qualitygate")).thenReturn(Long.toString(qGateId));
+    QualityGateDetails qGate = mock(QualityGateDetails.class);
+    when(qualityGateClient.show(qGateId)).thenReturn(qGate);
+    when(qGate.name()).thenReturn(qGateName);
+    assertThat(new QualityGateProvider().init(settings, client, logger).name()).isEqualTo(qGateName);
+    verify(logger).info("Loaded quality gate '{}'", qGateName);
+  }
+
+  @Test(expected = MessageException.class)
+  public void should_stop_analysis_if_gate_not_found() {
+    String qGateName = "Sonar way";
+    when(settings.getString("sonar.qualitygate")).thenReturn(qGateName);
+    when(qualityGateClient.show(qGateName)).thenThrow(new HttpException("http://server/api/qualitygates/show?name=Sonar%20way", HttpURLConnection.HTTP_NOT_FOUND));
+    new QualityGateProvider().provide(settings, client);
+  }
+
+  @Test(expected = HttpException.class)
+  public void should_stop_analysis_if_server_error() {
+    String qGateName = "Sonar way";
+    when(settings.getString("sonar.qualitygate")).thenReturn(qGateName);
+    when(qualityGateClient.show(qGateName)).thenThrow(new HttpException("http://server/api/qualitygates/show?name=Sonar%20way", HttpURLConnection.HTTP_NOT_ACCEPTABLE));
+    new QualityGateProvider().provide(settings, client);
+  }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java b/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java
new file mode 100644 (file)
index 0000000..4a56c23
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.batch.qualitygate;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.batch.DecoratorBarriers;
+import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Measure;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.core.timemachine.Periods;
+
+import java.util.Locale;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class QualityGateVerifierTest {
+
+  QualityGateVerifier verifier;
+  DecoratorContext context;
+  QualityGate qualityGate;
+
+  Measure measureClasses;
+  Measure measureCoverage;
+  Measure measureComplexity;
+  Resource project;
+  Snapshot snapshot;
+  Periods periods;
+  I18n i18n;
+
+  @Before
+  public void before() {
+    context = mock(DecoratorContext.class);
+    periods = mock(Periods.class);
+    i18n = mock(I18n.class);
+    when(i18n.message(any(Locale.class), eq("variation"), eq("variation"))).thenReturn("variation");
+
+    measureClasses = new Measure(CoreMetrics.CLASSES, 20d);
+    measureCoverage = new Measure(CoreMetrics.COVERAGE, 35d);
+    measureComplexity = new Measure(CoreMetrics.COMPLEXITY, 50d);
+
+    when(context.getMeasure(CoreMetrics.CLASSES)).thenReturn(measureClasses);
+    when(context.getMeasure(CoreMetrics.COVERAGE)).thenReturn(measureCoverage);
+    when(context.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(measureComplexity);
+
+    snapshot = mock(Snapshot.class);
+    qualityGate = mock(QualityGate.class);
+    when(qualityGate.isEnabled()).thenReturn(true);
+    verifier = new QualityGateVerifier(qualityGate);
+    project = new Project("foo");
+  }
+
+  @Test
+  public void should_be_executed_if_quality_gate_is_enabled() throws Exception {
+    assertThat(verifier.shouldExecuteOnProject((Project) project)).isTrue();
+    when(qualityGate.isEnabled()).thenReturn(false);
+    assertThat(verifier.shouldExecuteOnProject((Project) project)).isFalse();
+  }
+
+  @Test
+  public void test_toString() {
+    assertThat(verifier.toString()).isEqualTo("QualityGateVerifier");
+  }
+
+  @Test
+  public void generates_quality_gates_status() {
+    assertThat(verifier.generatesQualityGateStatus()).isEqualTo(CoreMetrics.QUALITY_GATE_STATUS);
+  }
+
+  @Test
+  public void depends_on_variations() {
+    assertThat(verifier.dependsOnVariations()).isEqualTo(DecoratorBarriers.END_OF_TIME_MACHINE);
+  }
+
+}