]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7488 add PostProjectAnalysisTaskTester 883/head
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 5 Apr 2016 17:15:30 +0000 (19:15 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Wed, 6 Apr 2016 13:42:53 +0000 (15:42 +0200)
sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTask.java
sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTester.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/CeTaskBuilder_PostProjectAnalysisTaskTesterTest.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/ConditionBuilder_PostProjectAnalysisTaskTesterTest.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTesterTest.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/ProjectBuilder_PostProjectAnalysisTaskTesterTest.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/QualityGateBuilder_PostProjectAnalysisTaskTesterTest.java [new file with mode: 0644]

index 630894008f392fc935bba02a9eda66bc3a4ce6db..11344fe57781f700be0ebadb7f5643d67c75462d 100644 (file)
@@ -29,9 +29,16 @@ import org.sonar.api.ce.ComputeEngineSide;
  * Extension point of which any plugin can provide an implementation and will allow them to be notified whenever some
  * analysis report processing ends in the Compute Engine.
  *
+ * <p>
  * If more then one implementation of {@link PostProjectAnalysisTask} is found, they will be executed in no specific order.
+ * </p>
+ *
+ * <p>
+ * Class {@link PostProjectAnalysisTaskTester} is provided to write unit tests of implementations of this interface.
+ * </p>
  *
  * @since 5.5
+ * @see PostProjectAnalysisTaskTester
  */
 @ExtensionPoint
 @ComputeEngineSide
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTester.java
new file mode 100644 (file)
index 0000000..1abe451
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.api.ce.posttask;
+
+import com.google.common.annotations.Beta;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * This class can be used to test {@link PostProjectAnalysisTask} implementations, see example below:
+ * <pre>
+ * import static org.assertj.core.api.Assertions.assertThat;
+ * import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newCeTaskBuilder;
+ * import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newConditionBuilder;
+ * import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newProjectBuilder;
+ * import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newQualityGateBuilder;
+ *
+ * public class CaptorPostProjectAnalysisTaskTest {
+ *   private class CaptorPostProjectAnalysisTask implements PostProjectAnalysisTask {
+ *     private ProjectAnalysis projectAnalysis;
+ *
+ *    {@literal @}Override
+ *     public void finished(ProjectAnalysis analysis) {
+ *       this.projectAnalysis = analysis;
+ *     }
+ *   }
+ *
+ *  {@literal @}Test
+ *   public void execute_is_passed_a_non_null_ProjectAnalysis_object() {
+ *     CaptorPostProjectAnalysisTask postProjectAnalysisTask = new CaptorPostProjectAnalysisTask();
+ *
+ *     PostProjectAnalysisTaskTester.of(postProjectAnalysisTask)
+ *       .withCeTask(
+ *           newCeTaskBuilder()
+ *               .setId("id")
+ *               .setStatus(CeTask.Status.SUCCESS)
+ *               .build())
+ *       .withProject(
+ *         PostProjectAnalysisTaskTester.newProjectBuilder()
+ *           .setUuid("uuid")
+ *           .setKey("key")
+ *           .setName("name")
+ *           .build())
+ *       .at(new Date())
+ *       .withQualityGate(
+ *         newQualityGateBuilder()
+ *           .setId("id")
+ *           .setName("name")
+ *           .setStatus(QualityGate.Status.OK)
+ *           .add(
+ *             newConditionBuilder()
+ *               .setMetricKey("metric key")
+ *               .setOperator(QualityGate.Operator.GREATER_THAN)
+ *               .setErrorThreshold("12")
+ *               .setOnLeakPeriod(true)
+ *               .build(QualityGate.EvaluationStatus.OK, "value"))
+ *           .build())
+ *       .execute();
+ *
+ *     assertThat(postProjectAnalysisTask.projectAnalysis).isNotNull();
+ *   }
+ * }
+ * </pre>
+ *
+ * @since 5.5
+ */
+@Beta
+public class PostProjectAnalysisTaskTester {
+  private static final String DATE_CAN_NOT_BE_NULL = "date can not be null";
+  private static final String PROJECT_CAN_NOT_BE_NULL = "project can not be null";
+  private static final String CE_TASK_CAN_NOT_BE_NULL = "ceTask can not be null";
+
+  private final PostProjectAnalysisTask underTest;
+  @CheckForNull
+  private CeTask ceTask;
+  @CheckForNull
+  private Project project;
+  @CheckForNull
+  private Date date;
+  @CheckForNull
+  private QualityGate qualityGate;
+
+  private PostProjectAnalysisTaskTester(PostProjectAnalysisTask underTest) {
+    this.underTest = requireNonNull(underTest, "PostProjectAnalysisTask instance can not be null");
+  }
+
+  public static PostProjectAnalysisTaskTester of(PostProjectAnalysisTask underTest) {
+    return new PostProjectAnalysisTaskTester(underTest);
+  }
+
+  public static CeTaskBuilder newCeTaskBuilder() {
+    return new CeTaskBuilder();
+  }
+
+  public static ProjectBuilder newProjectBuilder() {
+    return new ProjectBuilder();
+  }
+
+  public static QualityGateBuilder newQualityGateBuilder() {
+    return new QualityGateBuilder();
+  }
+
+  public static ConditionBuilder newConditionBuilder() {
+    return new ConditionBuilder();
+  }
+
+  public PostProjectAnalysisTaskTester withCeTask(CeTask ceTask) {
+    this.ceTask = requireNonNull(ceTask, CE_TASK_CAN_NOT_BE_NULL);
+    return this;
+  }
+
+  public PostProjectAnalysisTaskTester withProject(Project project) {
+    this.project = requireNonNull(project, PROJECT_CAN_NOT_BE_NULL);
+    return this;
+  }
+
+  public PostProjectAnalysisTaskTester at(Date date) {
+    this.date = requireNonNull(date, DATE_CAN_NOT_BE_NULL);
+    return this;
+  }
+
+  public PostProjectAnalysisTaskTester withQualityGate(@Nullable QualityGate qualityGate) {
+    this.qualityGate = qualityGate;
+    return this;
+  }
+
+  public void execute() {
+    this.ceTask = requireNonNull(ceTask, CE_TASK_CAN_NOT_BE_NULL);
+    this.project = requireNonNull(project, PROJECT_CAN_NOT_BE_NULL);
+    this.date = requireNonNull(date, DATE_CAN_NOT_BE_NULL);
+
+    this.underTest.finished(
+      new PostProjectAnalysisTask.ProjectAnalysis() {
+        @Override
+        public CeTask getCeTask() {
+          return ceTask;
+        }
+
+        @Override
+        public Project getProject() {
+          return project;
+        }
+
+        @Override
+        public QualityGate getQualityGate() {
+          return qualityGate;
+        }
+
+        @Override
+        public Date getDate() {
+          return date;
+        }
+
+        @Override
+        public String toString() {
+          return "ProjectAnalysis{" +
+            "ceTask=" + ceTask +
+            ", project=" + project +
+            ", date=" + date.getTime() +
+            ", qualityGate=" + qualityGate +
+            '}';
+        }
+      });
+
+  }
+
+  @Beta
+  public static final class CeTaskBuilder {
+    private static final String ID_CAN_NOT_BE_NULL = "id can not be null";
+    private static final String STATUS_CAN_NOT_BE_NULL = "status can not be null";
+
+    @CheckForNull
+    private String id;
+    @CheckForNull
+    private CeTask.Status status;
+
+    private CeTaskBuilder() {
+      // prevents instantiation outside PostProjectAnalysisTaskTester
+    }
+
+    public CeTaskBuilder setId(String id) {
+      this.id = requireNonNull(id, ID_CAN_NOT_BE_NULL);
+      return this;
+    }
+
+    public CeTaskBuilder setStatus(CeTask.Status status) {
+      this.status = requireNonNull(status, STATUS_CAN_NOT_BE_NULL);
+      return this;
+    }
+
+    public CeTask build() {
+      requireNonNull(id, ID_CAN_NOT_BE_NULL);
+      requireNonNull(status, STATUS_CAN_NOT_BE_NULL);
+      return new CeTask() {
+        @Override
+        public String getId() {
+          return id;
+        }
+
+        @Override
+        public Status getStatus() {
+          return status;
+        }
+
+        @Override
+        public String toString() {
+          return "CeTask{" +
+            "id='" + id + '\'' +
+            ", status=" + status +
+            '}';
+        }
+      };
+    }
+  }
+
+  @Beta
+  public static final class ProjectBuilder {
+    private static final String UUID_CAN_NOT_BE_NULL = "uuid can not be null";
+    private static final String KEY_CAN_NOT_BE_NULL = "key can not be null";
+    private static final String NAME_CAN_NOT_BE_NULL = "name can not be null";
+    private String uuid;
+    private String key;
+    private String name;
+
+    private ProjectBuilder() {
+      // prevents instantiation outside PostProjectAnalysisTaskTester
+    }
+
+    public ProjectBuilder setUuid(String uuid) {
+      this.uuid = requireNonNull(uuid, UUID_CAN_NOT_BE_NULL);
+      return this;
+    }
+
+    public ProjectBuilder setKey(String key) {
+      this.key = requireNonNull(key, KEY_CAN_NOT_BE_NULL);
+      return this;
+    }
+
+    public ProjectBuilder setName(String name) {
+      this.name = requireNonNull(name, NAME_CAN_NOT_BE_NULL);
+      return this;
+    }
+
+    public Project build() {
+      requireNonNull(uuid, UUID_CAN_NOT_BE_NULL);
+      requireNonNull(key, KEY_CAN_NOT_BE_NULL);
+      requireNonNull(name, NAME_CAN_NOT_BE_NULL);
+      return new Project() {
+        @Override
+        public String getUuid() {
+          return uuid;
+        }
+
+        @Override
+        public String getKey() {
+          return key;
+        }
+
+        @Override
+        public String getName() {
+          return name;
+        }
+
+        @Override
+        public String toString() {
+          return "Project{" +
+            "uuid='" + uuid + '\'' +
+            ", key='" + key + '\'' +
+            ", name='" + name + '\'' +
+            '}';
+        }
+
+      };
+    }
+  }
+
+  @Beta
+  public static final class QualityGateBuilder {
+    private static final String ID_CAN_NOT_BE_NULL = "id can not be null";
+    private static final String NAME_CAN_NOT_BE_NULL = "name can not be null";
+    private static final String STATUS_CAN_NOT_BE_NULL = "status can not be null";
+
+    private String id;
+    private String name;
+    private QualityGate.Status status;
+    private final List<QualityGate.Condition> conditions = new ArrayList<>();
+
+    private QualityGateBuilder() {
+      // prevents instantiation outside PostProjectAnalysisTaskTester
+    }
+
+    public QualityGateBuilder setId(String id) {
+      this.id = requireNonNull(id, ID_CAN_NOT_BE_NULL);
+      return this;
+    }
+
+    public QualityGateBuilder setName(String name) {
+      this.name = requireNonNull(name, NAME_CAN_NOT_BE_NULL);
+      return this;
+    }
+
+    public QualityGateBuilder setStatus(QualityGate.Status status) {
+      this.status = requireNonNull(status, STATUS_CAN_NOT_BE_NULL);
+      return this;
+    }
+
+    public QualityGateBuilder add(QualityGate.Condition condition) {
+      conditions.add(requireNonNull(condition, "condition can not be null"));
+      return this;
+    }
+
+    public QualityGateBuilder clearConditions() {
+      this.conditions.clear();
+      return this;
+    }
+
+    public QualityGate build() {
+      requireNonNull(id, ID_CAN_NOT_BE_NULL);
+      requireNonNull(name, NAME_CAN_NOT_BE_NULL);
+      requireNonNull(status, STATUS_CAN_NOT_BE_NULL);
+
+      return new QualityGate() {
+        @Override
+        public String getId() {
+          return id;
+        }
+
+        @Override
+        public String getName() {
+          return name;
+        }
+
+        @Override
+        public Status getStatus() {
+          return status;
+        }
+
+        @Override
+        public Collection<Condition> getConditions() {
+          return conditions;
+        }
+
+        @Override
+        public String toString() {
+          return "QualityGate{" +
+            "id='" + id + '\'' +
+            ", name='" + name + '\'' +
+            ", status=" + status +
+            ", conditions=" + conditions +
+            '}';
+        }
+      };
+    }
+  }
+
+  @Beta
+  public static final class ConditionBuilder {
+    private static final String METRIC_KEY_CAN_NOT_BE_NULL = "metricKey can not be null";
+    private static final String OPERATOR_CAN_NOT_BE_NULL = "operator can not be null";
+
+    private String metricKey;
+    private QualityGate.Operator operator;
+    private String errorThreshold;
+    private String warningThreshold;
+    private boolean onLeakPeriod;
+
+    private ConditionBuilder() {
+      // prevents instantiation outside PostProjectAnalysisTaskTester
+    }
+
+    public ConditionBuilder setMetricKey(String metricKey) {
+      this.metricKey = requireNonNull(metricKey, METRIC_KEY_CAN_NOT_BE_NULL);
+      return this;
+    }
+
+    public ConditionBuilder setOperator(QualityGate.Operator operator) {
+      this.operator = requireNonNull(operator, OPERATOR_CAN_NOT_BE_NULL);
+      return this;
+    }
+
+    public ConditionBuilder setErrorThreshold(@Nullable String errorThreshold) {
+      this.errorThreshold = errorThreshold;
+      return this;
+    }
+
+    public ConditionBuilder setWarningThreshold(@Nullable String warningThreshold) {
+      this.warningThreshold = warningThreshold;
+      return this;
+    }
+
+    public ConditionBuilder setOnLeakPeriod(boolean onLeakPeriod) {
+      this.onLeakPeriod = onLeakPeriod;
+      return this;
+    }
+
+    public QualityGate.Condition buildNoValue() {
+      checkCommonProperties();
+      return new QualityGate.Condition() {
+        @Override
+        public QualityGate.EvaluationStatus getStatus() {
+          return QualityGate.EvaluationStatus.NO_VALUE;
+        }
+
+        @Override
+        public String getMetricKey() {
+          return metricKey;
+        }
+
+        @Override
+        public QualityGate.Operator getOperator() {
+          return operator;
+        }
+
+        @Override
+        public String getErrorThreshold() {
+          return errorThreshold;
+        }
+
+        @Override
+        public String getWarningThreshold() {
+          return warningThreshold;
+        }
+
+        @Override
+        public boolean isOnLeakPeriod() {
+          return onLeakPeriod;
+        }
+
+        @Override
+        public String getValue() {
+          throw new IllegalStateException("There is no value when status is NO_VALUE");
+        }
+
+        @Override
+        public String toString() {
+          return "Condition{" +
+            "status=" + QualityGate.EvaluationStatus.NO_VALUE +
+            ", metricKey='" + metricKey + '\'' +
+            ", operator=" + operator +
+            ", errorThreshold='" + errorThreshold + '\'' +
+            ", warningThreshold='" + warningThreshold + '\'' +
+            ", onLeakPeriod=" + onLeakPeriod +
+            '}';
+        }
+      };
+    }
+
+    public QualityGate.Condition build(final QualityGate.EvaluationStatus status, final String value) {
+      checkCommonProperties();
+      requireNonNull(status, "status can not be null");
+      checkArgument(status != QualityGate.EvaluationStatus.NO_VALUE, "status can not be NO_VALUE, use method buildNoValue() instead");
+      requireNonNull(value, "value can not be null, use method buildNoValue() instead");
+      return new QualityGate.Condition() {
+        @Override
+        public QualityGate.EvaluationStatus getStatus() {
+          return status;
+        }
+
+        @Override
+        public String getMetricKey() {
+          return metricKey;
+        }
+
+        @Override
+        public QualityGate.Operator getOperator() {
+          return operator;
+        }
+
+        @Override
+        public String getErrorThreshold() {
+          return errorThreshold;
+        }
+
+        @Override
+        public String getWarningThreshold() {
+          return warningThreshold;
+        }
+
+        @Override
+        public boolean isOnLeakPeriod() {
+          return onLeakPeriod;
+        }
+
+        @Override
+        public String getValue() {
+          return value;
+        }
+
+        @Override
+        public String toString() {
+          return "Condition{" +
+            "status=" + status +
+            ", metricKey='" + metricKey + '\'' +
+            ", operator=" + operator +
+            ", errorThreshold='" + errorThreshold + '\'' +
+            ", warningThreshold='" + warningThreshold + '\'' +
+            ", onLeakPeriod=" + onLeakPeriod +
+            ", value='" + value + '\'' +
+            '}';
+        }
+      };
+    }
+
+    private void checkCommonProperties() {
+      requireNonNull(metricKey, METRIC_KEY_CAN_NOT_BE_NULL);
+      requireNonNull(operator, OPERATOR_CAN_NOT_BE_NULL);
+      checkState(errorThreshold != null || warningThreshold != null, "At least one of errorThreshold and warningThreshold must be non null");
+    }
+  }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/CeTaskBuilder_PostProjectAnalysisTaskTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/CeTaskBuilder_PostProjectAnalysisTaskTesterTest.java
new file mode 100644 (file)
index 0000000..4425b0f
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.api.ce.posttask;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CeTaskBuilder_PostProjectAnalysisTaskTesterTest {
+  private static final CeTask.Status SOME_STATUS = CeTask.Status.SUCCESS;
+  private static final String SOME_ID = "some id";
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private PostProjectAnalysisTaskTester.CeTaskBuilder underTest = PostProjectAnalysisTaskTester.newCeTaskBuilder();
+
+  @Test
+  public void setId_throws_NPE_if_id_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("id can not be null");
+
+    underTest.setId(null);
+  }
+
+  @Test
+  public void setStatus_throws_NPE_if_status_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("status can not be null");
+
+    underTest.setStatus(null);
+  }
+
+  @Test
+  public void build_throws_NPE_if_id_is_null() {
+    underTest.setStatus(SOME_STATUS);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("id can not be null");
+
+    underTest.build();
+  }
+
+  @Test
+  public void build_throws_NPE_if_status_is_null() {
+    underTest.setId(SOME_ID);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("status can not be null");
+
+    underTest.build();
+  }
+
+  @Test
+  public void build_returns_new_instance_at_each_call() {
+    underTest.setId(SOME_ID).setStatus(SOME_STATUS);
+
+    assertThat(underTest.build()).isNotSameAs(underTest.build());
+  }
+
+  @Test
+  public void verify_getters() {
+    CeTask ceTask = underTest.setId(SOME_ID).setStatus(SOME_STATUS).build();
+
+    assertThat(ceTask.getId()).isEqualTo(SOME_ID);
+    assertThat(ceTask.getStatus()).isEqualTo(SOME_STATUS);
+  }
+
+  @Test
+  public void verify_toString() {
+    assertThat(underTest.setId(SOME_ID).setStatus(SOME_STATUS).build().toString()).isEqualTo("CeTask{id='some id', status=SUCCESS}");
+  }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/ConditionBuilder_PostProjectAnalysisTaskTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/ConditionBuilder_PostProjectAnalysisTaskTesterTest.java
new file mode 100644 (file)
index 0000000..c6ab146
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.api.ce.posttask;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ConditionBuilder_PostProjectAnalysisTaskTesterTest {
+  private static final String SOME_METRIC_KEY = "some metric key";
+  private static final QualityGate.Operator SOME_OPERATOR = QualityGate.Operator.GREATER_THAN;
+  private static final String SOME_ERROR_THRESHOLD = "some error threshold";
+  private static final String SOME_WARNING_THRESHOLD = "some warning threshold";
+  private static final QualityGate.EvaluationStatus SOME_STATUS_BUT_NO_VALUE = QualityGate.EvaluationStatus.OK;
+  private static final String SOME_VALUE = "some value";
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private PostProjectAnalysisTaskTester.ConditionBuilder underTest = PostProjectAnalysisTaskTester.newConditionBuilder();
+
+  @Test
+  public void setMetricKey_throws_NPE_if_operator_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("metricKey can not be null");
+
+    underTest.setMetricKey(null);
+  }
+
+  @Test
+  public void setOperator_throws_NPE_if_operator_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("operator can not be null");
+
+    underTest.setOperator(null);
+  }
+
+  @Test
+  public void buildNoValue_throws_NPE_if_metricKey_is_null() {
+    underTest.setOperator(SOME_OPERATOR).setErrorThreshold(SOME_ERROR_THRESHOLD).setWarningThreshold(SOME_WARNING_THRESHOLD);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("metricKey can not be null");
+
+    underTest.buildNoValue();
+  }
+
+  @Test
+  public void buildNoValue_throws_NPE_if_operator_is_null() {
+    underTest.setMetricKey(SOME_METRIC_KEY).setErrorThreshold(SOME_ERROR_THRESHOLD).setWarningThreshold(SOME_WARNING_THRESHOLD);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("operator can not be null");
+
+    underTest.buildNoValue();
+  }
+
+  @Test
+  public void buildNoValue_throws_ISE_if_both_warningThreshold_and_errorThreshold_are_null() {
+    underTest.setMetricKey(SOME_METRIC_KEY).setOperator(SOME_OPERATOR);
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("At least one of errorThreshold and warningThreshold must be non null");
+
+    underTest.buildNoValue();
+  }
+
+  @Test
+  public void buildNoValue_returns_Condition_which_getStatus_method_returns_NO_VALUE() {
+    initValidBuilder();
+
+    assertThat(underTest.buildNoValue().getStatus()).isEqualTo(QualityGate.EvaluationStatus.NO_VALUE);
+  }
+
+  @Test
+  public void buildNoValue_returns_Condition_which_getValue_method_throws_ISE() {
+    initValidBuilder();
+    QualityGate.Condition condition = underTest.buildNoValue();
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("There is no value when status is NO_VALUE");
+
+    condition.getValue();
+  }
+
+  @Test
+  public void buildNoValue_does_not_fail_when_only_errorThreshold_is_set() {
+    underTest.setMetricKey(SOME_METRIC_KEY).setOperator(SOME_OPERATOR).setErrorThreshold(SOME_ERROR_THRESHOLD);
+
+    underTest.buildNoValue();
+  }
+
+  @Test
+  public void buildNoValue_does_not_fail_when_only_wardThreshold_is_set() {
+    underTest.setMetricKey(SOME_METRIC_KEY).setOperator(SOME_OPERATOR).setWarningThreshold(SOME_WARNING_THRESHOLD);
+
+    underTest.buildNoValue();
+  }
+
+  @Test
+  public void buildNoValue_returns_new_instance_at_each_call() {
+    initValidBuilder();
+
+    assertThat(underTest.buildNoValue()).isNotSameAs(underTest.buildNoValue());
+  }
+
+  @Test
+  public void buildNoValue_has_no_value_in_toString_and_status_is_NO_VALUE() {
+    initValidBuilder();
+
+    assertThat(underTest.buildNoValue().toString())
+      .isEqualTo(
+        "Condition{status=NO_VALUE, metricKey='some metric key', operator=GREATER_THAN, " +
+          "errorThreshold='some error threshold', warningThreshold='some warning threshold', onLeakPeriod=false}");
+  }
+
+  @Test
+  public void verify_getters_of_object_returned_by_buildNoValue() {
+    initValidBuilder().setOnLeakPeriod(true);
+
+    QualityGate.Condition condition = underTest.buildNoValue();
+
+    assertThat(condition.getMetricKey()).isEqualTo(SOME_METRIC_KEY);
+    assertThat(condition.getOperator()).isEqualTo(SOME_OPERATOR);
+    assertThat(condition.getErrorThreshold()).isEqualTo(SOME_ERROR_THRESHOLD);
+    assertThat(condition.getWarningThreshold()).isEqualTo(SOME_WARNING_THRESHOLD);
+    assertThat(condition.isOnLeakPeriod()).isTrue();
+  }
+
+  @Test
+  public void build_throws_NPE_if_status_is_null() {
+    initValidBuilder();
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("status can not be null");
+
+    underTest.build(null, SOME_VALUE);
+  }
+
+  @Test
+  public void build_throws_IAE_if_status_is_NO_VALUE() {
+    initValidBuilder();
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("status can not be NO_VALUE, use method buildNoValue() instead");
+
+    underTest.build(QualityGate.EvaluationStatus.NO_VALUE, SOME_VALUE);
+  }
+
+  @Test
+  public void build_throws_NPE_if_value_is_null() {
+    initValidBuilder();
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("value can not be null, use method buildNoValue() instead");
+
+    underTest.build(SOME_STATUS_BUT_NO_VALUE, null);
+  }
+
+  @Test
+  public void build_throws_NPE_if_metricKey_is_null() {
+    underTest.setOperator(SOME_OPERATOR).setErrorThreshold(SOME_ERROR_THRESHOLD).setWarningThreshold(SOME_WARNING_THRESHOLD);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("metricKey can not be null");
+
+    underTest.build(SOME_STATUS_BUT_NO_VALUE, SOME_VALUE);
+  }
+
+  @Test
+  public void build_throws_NPE_if_operator_is_null() {
+    underTest.setMetricKey(SOME_METRIC_KEY).setErrorThreshold(SOME_ERROR_THRESHOLD).setWarningThreshold(SOME_WARNING_THRESHOLD);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("operator can not be null");
+
+    underTest.build(SOME_STATUS_BUT_NO_VALUE, SOME_VALUE);
+  }
+
+  @Test
+  public void build_does_not_fail_when_only_errorThreshold_is_set() {
+    underTest.setMetricKey(SOME_METRIC_KEY).setOperator(SOME_OPERATOR).setErrorThreshold(SOME_ERROR_THRESHOLD);
+
+    underTest.build(SOME_STATUS_BUT_NO_VALUE, SOME_VALUE);
+  }
+
+  @Test
+  public void build_does_not_fail_when_only_wardThreshold_is_set() {
+    underTest.setMetricKey(SOME_METRIC_KEY).setOperator(SOME_OPERATOR).setWarningThreshold(SOME_WARNING_THRESHOLD);
+
+    underTest.build(SOME_STATUS_BUT_NO_VALUE, SOME_VALUE);
+  }
+
+  @Test
+  public void build_throws_ISE_if_both_warningThreshold_and_errorThreshold_are_null() {
+    underTest.setMetricKey(SOME_METRIC_KEY).setOperator(SOME_OPERATOR);
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("At least one of errorThreshold and warningThreshold must be non null");
+
+    underTest.build(SOME_STATUS_BUT_NO_VALUE, SOME_VALUE);
+  }
+
+  @Test
+  public void build_returns_new_instance_at_each_call() {
+    initValidBuilder();
+
+    assertThat(underTest.build(SOME_STATUS_BUT_NO_VALUE, SOME_VALUE)).isNotSameAs(underTest.build(SOME_STATUS_BUT_NO_VALUE, SOME_VALUE));
+  }
+
+  @Test
+  public void build_has_value_in_toString_and_specified_status() {
+    initValidBuilder();
+
+    assertThat(underTest.build(SOME_STATUS_BUT_NO_VALUE, SOME_VALUE).toString())
+      .isEqualTo(
+        "Condition{status=OK, metricKey='some metric key', operator=GREATER_THAN, "
+          + "errorThreshold='some error threshold', warningThreshold='some warning threshold', onLeakPeriod=false, value='some value'}");
+  }
+
+  @Test
+  public void build_returns_Condition_which_getStatus_method_returns_NO_VALUE() {
+    initValidBuilder();
+
+    assertThat(underTest.buildNoValue().getStatus()).isEqualTo(QualityGate.EvaluationStatus.NO_VALUE);
+  }
+
+  @Test
+  public void build_returns_Condition_which_getValue_method_throws_ISE() {
+    initValidBuilder();
+    QualityGate.Condition condition = underTest.buildNoValue();
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("There is no value when status is NO_VALUE");
+
+    condition.getValue();
+  }
+
+  @Test
+  public void verify_getters_of_object_returned_by_build() {
+    initValidBuilder().setOnLeakPeriod(true);
+
+    QualityGate.Condition condition = underTest.build(SOME_STATUS_BUT_NO_VALUE, SOME_VALUE);
+
+    assertThat(condition.getStatus()).isEqualTo(SOME_STATUS_BUT_NO_VALUE);
+    assertThat(condition.getMetricKey()).isEqualTo(SOME_METRIC_KEY);
+    assertThat(condition.getOperator()).isEqualTo(SOME_OPERATOR);
+    assertThat(condition.getErrorThreshold()).isEqualTo(SOME_ERROR_THRESHOLD);
+    assertThat(condition.getWarningThreshold()).isEqualTo(SOME_WARNING_THRESHOLD);
+    assertThat(condition.isOnLeakPeriod()).isTrue();
+    assertThat(condition.getValue()).isEqualTo(SOME_VALUE);
+  }
+
+  @Test
+  public void isOnLeakPeriod_is_false_by_default() {
+    initValidBuilder();
+
+    assertThat(underTest.buildNoValue().isOnLeakPeriod()).isFalse();
+    assertThat(underTest.build(SOME_STATUS_BUT_NO_VALUE, SOME_VALUE).isOnLeakPeriod()).isFalse();
+  }
+
+  @Test
+  public void isOnLeakPeriod_changes_isOnLeakPeriod_returned_value() {
+    initValidBuilder().setOnLeakPeriod(true);
+
+    assertThat(underTest.buildNoValue().isOnLeakPeriod()).isTrue();
+    assertThat(underTest.build(SOME_STATUS_BUT_NO_VALUE, SOME_VALUE).isOnLeakPeriod()).isTrue();
+
+    initValidBuilder().setOnLeakPeriod(false);
+
+    assertThat(underTest.buildNoValue().isOnLeakPeriod()).isFalse();
+    assertThat(underTest.build(SOME_STATUS_BUT_NO_VALUE, SOME_VALUE).isOnLeakPeriod()).isFalse();
+  }
+
+  private PostProjectAnalysisTaskTester.ConditionBuilder initValidBuilder() {
+    underTest.setMetricKey(SOME_METRIC_KEY).setOperator(SOME_OPERATOR).setErrorThreshold(SOME_ERROR_THRESHOLD).setWarningThreshold(SOME_WARNING_THRESHOLD);
+    return underTest;
+  }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/PostProjectAnalysisTaskTesterTest.java
new file mode 100644 (file)
index 0000000..320a334
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.api.ce.posttask;
+
+import java.util.Date;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class PostProjectAnalysisTaskTesterTest {
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private CeTask ceTask = mock(CeTask.class);
+  private Project project = mock(Project.class);
+  private long someDateAsLong = 846351351684351L;
+  private Date someDate = new Date(someDateAsLong);
+  private QualityGate qualityGate = mock(QualityGate.class);
+  private CaptorPostProjectAnalysisTask captorPostProjectAnalysisTask = new CaptorPostProjectAnalysisTask();
+  private PostProjectAnalysisTaskTester underTest = PostProjectAnalysisTaskTester.of(captorPostProjectAnalysisTask);
+
+  @Test
+  public void of_throws_NPE_if_PostProjectAnalysisTask_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("PostProjectAnalysisTask instance can not be null");
+
+    PostProjectAnalysisTaskTester.of(null);
+  }
+
+  @Test
+  public void withCeTask_throws_NPE_if_ceTask_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("ceTask can not be null");
+
+    underTest.withCeTask(null);
+  }
+
+  @Test
+  public void withProject_throws_NPE_if_project_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("project can not be null");
+
+    underTest.withProject(null);
+  }
+
+  @Test
+  public void at_throws_NPE_if_date_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("date can not be null");
+
+    underTest.at(null);
+  }
+
+  @Test
+  public void withQualityGate_does_not_throw_NPE_if_project_is_null() {
+    underTest.withQualityGate(null);
+  }
+
+  @Test
+  public void execute_throws_NPE_if_ceTask_is_null() {
+    underTest.withProject(project).at(someDate);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("ceTask can not be null");
+
+    underTest.execute();
+  }
+
+  @Test
+  public void execute_throws_NPE_if_project_is_null() {
+    underTest.withCeTask(ceTask).at(someDate);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("project can not be null");
+
+    underTest.execute();
+  }
+
+  @Test
+  public void verify_getters_of_ProjectAnalysis_object_passed_to_PostProjectAnalysisTask() {
+    underTest.withCeTask(ceTask).withProject(project).withQualityGate(qualityGate).at(someDate);
+
+    underTest.execute();
+
+    PostProjectAnalysisTask.ProjectAnalysis projectAnalysis = captorPostProjectAnalysisTask.projectAnalysis;
+    assertThat(projectAnalysis).isNotNull();
+    assertThat(projectAnalysis.getCeTask()).isSameAs(ceTask);
+    assertThat(projectAnalysis.getProject()).isSameAs(project);
+    assertThat(projectAnalysis.getDate()).isSameAs(someDate);
+    assertThat(projectAnalysis.getQualityGate()).isSameAs(qualityGate);
+  }
+
+  @Test
+  public void verify_toString_of_ProjectAnalysis_object_passed_to_PostProjectAnalysisTask() {
+    when(ceTask.toString()).thenReturn("CeTask");
+    when(project.toString()).thenReturn("Project");
+    when(qualityGate.toString()).thenReturn("QualityGate");
+    underTest.withCeTask(ceTask).withProject(project).withQualityGate(qualityGate).at(someDate);
+
+    underTest.execute();
+
+    assertThat(captorPostProjectAnalysisTask.projectAnalysis.toString())
+      .isEqualTo("ProjectAnalysis{ceTask=CeTask, project=Project, date=846351351684351, qualityGate=QualityGate}");
+
+  }
+
+  @Test
+  public void execute_throws_NPE_if_date_is_null() {
+    underTest.withCeTask(ceTask).withProject(project);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("date can not be null");
+
+    underTest.execute();
+  }
+
+  private static class CaptorPostProjectAnalysisTask implements PostProjectAnalysisTask {
+    private ProjectAnalysis projectAnalysis;
+
+    @Override
+    public void finished(ProjectAnalysis analysis) {
+      this.projectAnalysis = analysis;
+    }
+  }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/ProjectBuilder_PostProjectAnalysisTaskTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/ProjectBuilder_PostProjectAnalysisTaskTesterTest.java
new file mode 100644 (file)
index 0000000..25bc2d4
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.api.ce.posttask;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ProjectBuilder_PostProjectAnalysisTaskTesterTest {
+  private static final String SOME_NAME = "some name";
+  private static final String SOME_KEY = "some key";
+  private static final String SOME_UUID = "some uuid";
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private PostProjectAnalysisTaskTester.ProjectBuilder underTest = PostProjectAnalysisTaskTester.newProjectBuilder();
+
+  @Test
+  public void setKey_throws_NPE_if_key_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("key can not be null");
+
+    underTest.setKey(null);
+  }
+
+  @Test
+  public void setName_throws_NPE_if_name_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("name can not be null");
+
+    underTest.setName(null);
+  }
+
+  @Test
+  public void setUuid_throws_NPE_if_uuid_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("uuid can not be null");
+
+    underTest.setUuid(null);
+  }
+
+  @Test
+  public void build_throws_NPE_if_key_is_null() {
+    underTest.setUuid(SOME_UUID).setName(SOME_NAME);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("key can not be null");
+
+    underTest.build();
+  }
+
+  @Test
+  public void build_throws_NPE_if_name_is_null() {
+    underTest.setUuid(SOME_UUID).setKey(SOME_KEY);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("name can not be null");
+
+
+    underTest.build();
+  }
+
+  @Test
+  public void build_throws_NPE_if_uuid_is_null() {
+    underTest.setKey(SOME_KEY).setName(SOME_NAME);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("uuid can not be null");
+
+    underTest.build();
+  }
+
+  @Test
+  public void build_returns_new_instance_at_each_call() {
+    underTest.setUuid(SOME_UUID).setKey(SOME_KEY).setName(SOME_NAME);
+
+    assertThat(underTest.build()).isNotSameAs(underTest.build());
+  }
+
+  @Test
+  public void verify_getters() {
+    Project project = underTest.setUuid(SOME_UUID).setKey(SOME_KEY).setName(SOME_NAME).build();
+
+    assertThat(project.getUuid()).isEqualTo(SOME_UUID);
+    assertThat(project.getKey()).isEqualTo(SOME_KEY);
+    assertThat(project.getName()).isEqualTo(SOME_NAME);
+  }
+
+  @Test
+  public void verify_toString() {
+    assertThat(underTest.setUuid(SOME_UUID).setKey(SOME_KEY).setName(SOME_NAME).build().toString())
+      .isEqualTo("Project{uuid='some uuid', key='some key', name='some name'}");
+  }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/QualityGateBuilder_PostProjectAnalysisTaskTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/ce/posttask/QualityGateBuilder_PostProjectAnalysisTaskTesterTest.java
new file mode 100644 (file)
index 0000000..61a466b
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.api.ce.posttask;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class QualityGateBuilder_PostProjectAnalysisTaskTesterTest {
+  private static final String SOME_NAME = "some name";
+  private static final QualityGate.Status SOME_STATUS = QualityGate.Status.ERROR;
+  private static final String SOME_ID = "some id";
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private QualityGate.Condition condition1 = mock(QualityGate.Condition.class);
+  private QualityGate.Condition condition2 = mock(QualityGate.Condition.class);
+  private PostProjectAnalysisTaskTester.QualityGateBuilder underTest = PostProjectAnalysisTaskTester.newQualityGateBuilder();
+
+  @Test
+  public void setId_throws_NPE_if_id_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("id can not be null");
+
+    underTest.setId(null);
+  }
+
+  @Test
+  public void setStatus_throws_NPE_if_status_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("status can not be null");
+
+    underTest.setStatus(null);
+  }
+
+  @Test
+  public void setName_throws_NPE_if_name_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("name can not be null");
+
+    underTest.setName(null);
+  }
+
+  @Test
+  public void addCondition_throws_NPE_if_condition_is_null() {
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("condition can not be null");
+
+    underTest.add(null);
+  }
+
+  @Test
+  public void clearConditions_does_not_raise_any_error_if_there_is_no_condition_in_builder() {
+    underTest.clearConditions();
+  }
+
+  @Test
+  public void clearConditions_removes_all_conditions_from_builder() {
+    underTest.setId(SOME_ID).setStatus(SOME_STATUS).setName(SOME_NAME).add(condition1).add(condition2);
+
+    assertThat(underTest.build().getConditions()).containsOnly(condition1, condition2);
+
+    underTest.clearConditions();
+
+    assertThat(underTest.build().getConditions()).isEmpty();
+  }
+
+  @Test
+  public void build_throws_NPE_if_id_is_null() {
+    underTest.setStatus(SOME_STATUS).setName(SOME_NAME);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("id can not be null");
+
+    underTest.build();
+  }
+
+  @Test
+  public void build_throws_NPE_if_status_is_null() {
+    underTest.setId(SOME_ID).setName(SOME_NAME);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("status can not be null");
+
+    underTest.build();
+  }
+
+  @Test
+  public void build_throws_NPE_if_name_is_null() {
+    underTest.setId(SOME_ID).setStatus(SOME_STATUS);
+
+    expectedException.expect(NullPointerException.class);
+    expectedException.expectMessage("name can not be null");
+
+    underTest.build();
+  }
+
+  @Test
+  public void build_returns_new_instance_at_each_call() {
+    underTest.setId(SOME_ID).setStatus(SOME_STATUS).setName(SOME_NAME);
+
+    assertThat(underTest.build()).isNotSameAs(underTest.build());
+  }
+
+  @Test
+  public void verify_getters() {
+    QualityGate qualityGate = underTest.setId(SOME_ID).setStatus(SOME_STATUS).setName(SOME_NAME).add(condition1).add(condition2).build();
+
+    assertThat(qualityGate.getId()).isEqualTo(SOME_ID);
+    assertThat(qualityGate.getStatus()).isEqualTo(SOME_STATUS);
+    assertThat(qualityGate.getName()).isEqualTo(SOME_NAME);
+    assertThat(qualityGate.getConditions()).containsOnly(condition1, condition2);
+  }
+
+  @Test
+  public void verify_toString() {
+    when(condition1.toString()).thenReturn("condition1");
+    when(condition2.toString()).thenReturn("condition2");
+
+    assertThat(underTest.setId(SOME_ID).setStatus(SOME_STATUS).setName(SOME_NAME).add(condition1).add(condition2).build().toString())
+      .isEqualTo("QualityGate{id='some id', name='some name', status=ERROR, conditions=[condition1, condition2]}");
+  }
+}