]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7276 support multiple conditions for a given metric in QG 932/head
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 9 May 2016 09:26:06 +0000 (11:26 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 12 May 2016 10:11:42 +0000 (12:11 +0200)
they must have a different period

server/sonar-server/src/main/java/org/sonar/server/computation/step/QualityGateMeasuresStep.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/QualityGateMeasuresStepTest.java

index affc20eec8a59e85095ab9dff4bc758e58a2c768..5f9dca9b7e2ce8e7b6e06baca49b44ce1f0cca9d 100644 (file)
@@ -22,7 +22,10 @@ package org.sonar.server.computation.step;
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Ordering;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -69,6 +72,8 @@ import static org.sonar.server.computation.qualitygate.ConditionStatus.create;
  * It must be executed after the computation of differential measures {@link ComputeMeasureVariationsStep}
  */
 public class QualityGateMeasuresStep implements ComputationStep {
+  private static final Ordering<Condition> PERIOD_ORDERING = Ordering.natural().nullsLast()
+    .onResultOf(ConditionToPeriod.INSTANCE);
 
   private final TreeRootHolder treeRootHolder;
   private final QualityGateHolder qualityGateHolder;
@@ -164,24 +169,37 @@ public class QualityGateMeasuresStep implements ComputationStep {
   }
 
   private void updateMeasures(Component project, Set<Condition> conditions, QualityGateDetailsDataBuilder builder) {
-    for (Condition condition : conditions) {
-      Optional<Measure> measure = measureRepository.getRawMeasure(project, condition.getMetric());
+    Multimap<Metric, Condition> conditionsPerMetric = from(conditions).index(ConditionToMetric.INSTANCE);
+    for (Map.Entry<Metric, Collection<Condition>> entry : conditionsPerMetric.asMap().entrySet()) {
+      Metric metric = entry.getKey();
+      Optional<Measure> measure = measureRepository.getRawMeasure(project, metric);
       if (!measure.isPresent()) {
         continue;
       }
 
-      EvaluationResult evaluationResult = new ConditionEvaluator().evaluate(condition, measure.get());
-
-      String text = evaluationResultTextConverter.asText(condition, evaluationResult);
+      MetricEvaluationResult metricEvaluationResult = evaluateQualityGate(measure.get(), entry.getValue());
+      String text = evaluationResultTextConverter.asText(metricEvaluationResult.condition, metricEvaluationResult.evaluationResult);
       builder.addLabel(text);
 
       Measure updatedMeasure = Measure.updatedMeasureBuilder(measure.get())
-        .setQualityGateStatus(new QualityGateStatus(evaluationResult.getLevel(), text))
+        .setQualityGateStatus(new QualityGateStatus(metricEvaluationResult.evaluationResult.getLevel(), text))
         .create();
-      measureRepository.update(project, condition.getMetric(), updatedMeasure);
+      measureRepository.update(project, metric, updatedMeasure);
+
+      builder.addEvaluatedCondition(metricEvaluationResult);
+    }
+  }
 
-      builder.addEvaluatedCondition(condition, evaluationResult);
+  private static MetricEvaluationResult evaluateQualityGate(Measure measure, Collection<Condition> conditions) {
+    ConditionEvaluator conditionEvaluator = new ConditionEvaluator();
+    MetricEvaluationResult metricEvaluationResult = null;
+    for (Condition newCondition : PERIOD_ORDERING.immutableSortedCopy(conditions)) {
+      EvaluationResult newEvaluationResult = conditionEvaluator.evaluate(newCondition, measure);
+      if (metricEvaluationResult == null || newEvaluationResult.getLevel().ordinal() > metricEvaluationResult.evaluationResult.getLevel().ordinal()) {
+        metricEvaluationResult = new MetricEvaluationResult(newEvaluationResult, newCondition);
+      }
     }
+    return metricEvaluationResult;
   }
 
   private void addProjectMeasure(Component project, QualityGateDetailsDataBuilder builder) {
@@ -221,14 +239,16 @@ public class QualityGateMeasuresStep implements ComputationStep {
       return labels;
     }
 
-    public void addEvaluatedCondition(Condition condition, EvaluationResult evaluationResult) {
-      if (Measure.Level.WARN == evaluationResult.getLevel() && this.globalLevel != Measure.Level.ERROR) {
+    public void addEvaluatedCondition(MetricEvaluationResult metricEvaluationResult) {
+      Measure.Level level = metricEvaluationResult.evaluationResult.getLevel();
+      if (Measure.Level.WARN == level && this.globalLevel != Measure.Level.ERROR) {
         globalLevel = Measure.Level.WARN;
 
-      } else if (Measure.Level.ERROR == evaluationResult.getLevel()) {
+      } else if (Measure.Level.ERROR == level) {
         globalLevel = Measure.Level.ERROR;
       }
-      evaluatedConditions.add(new EvaluatedCondition(condition, evaluationResult.getLevel(), evaluationResult.getValue()));
+      evaluatedConditions.add(
+        new EvaluatedCondition(metricEvaluationResult.condition, level, metricEvaluationResult.evaluationResult.getValue()));
     }
 
     public List<EvaluatedCondition> getEvaluatedConditions() {
@@ -245,4 +265,34 @@ public class QualityGateMeasuresStep implements ComputationStep {
       return input.getCondition();
     }
   }
+
+  private static class MetricEvaluationResult {
+    private final EvaluationResult evaluationResult;
+    private final Condition condition;
+
+    private MetricEvaluationResult(EvaluationResult evaluationResult, Condition condition) {
+      this.evaluationResult = evaluationResult;
+      this.condition = condition;
+    }
+  }
+
+  private enum ConditionToMetric implements Function<Condition, Metric> {
+    INSTANCE;
+
+    @Override
+    @Nonnull
+    public Metric apply(@Nonnull Condition input) {
+      return input.getMetric();
+    }
+  }
+
+  public enum ConditionToPeriod implements Function<Condition, Integer> {
+    INSTANCE;
+
+    @Override
+    @Nullable
+    public Integer apply(@Nonnull Condition input) {
+      return input.getPeriod();
+    }
+  }
 }
index 20cb102fc26001e02db5e7f04962e4222bbe0e67..51df268f461af802b36ed8d5616df8e2e0c6abdb 100644 (file)
@@ -29,7 +29,6 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 import org.sonar.api.measures.CoreMetrics;
@@ -37,12 +36,13 @@ import org.sonar.server.computation.batch.TreeRootHolderRule;
 import org.sonar.server.computation.component.Component;
 import org.sonar.server.computation.component.ReportComponent;
 import org.sonar.server.computation.measure.Measure;
-import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.measure.MeasureRepositoryRule;
 import org.sonar.server.computation.measure.qualitygatedetails.EvaluatedCondition;
 import org.sonar.server.computation.measure.qualitygatedetails.QualityGateDetailsData;
 import org.sonar.server.computation.metric.Metric;
 import org.sonar.server.computation.metric.MetricImpl;
-import org.sonar.server.computation.metric.MetricRepository;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+import org.sonar.server.computation.period.Period;
 import org.sonar.server.computation.qualitygate.Condition;
 import org.sonar.server.computation.qualitygate.ConditionStatus;
 import org.sonar.server.computation.qualitygate.EvaluationResult;
@@ -55,21 +55,24 @@ import org.sonar.server.computation.qualitygate.QualityGateStatusHolder;
 
 import static com.google.common.collect.ImmutableList.of;
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.same;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
+import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
 import static org.sonar.server.computation.measure.Measure.Level.ERROR;
 import static org.sonar.server.computation.measure.Measure.Level.OK;
 import static org.sonar.server.computation.measure.Measure.Level.WARN;
+import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
 import static org.sonar.server.computation.measure.MeasureAssert.assertThat;
+import static org.sonar.server.computation.measure.MeasureVariations.newMeasureVariationsBuilder;
 
 public class QualityGateMeasuresStepTest {
   private static final MetricImpl INT_METRIC_1 = createIntMetric(1);
+  private static final String INT_METRIC_1_KEY = INT_METRIC_1.getKey();
   private static final MetricImpl INT_METRIC_2 = createIntMetric(2);
+  private static final String INT_METRIC_2_KEY = INT_METRIC_2.getKey();
 
-  private static final ReportComponent PROJECT_COMPONENT = ReportComponent.builder(Component.Type.PROJECT, 1).build();
+  private static final int PROJECT_REF = 1;
+  private static final ReportComponent PROJECT_COMPONENT = ReportComponent.builder(Component.Type.PROJECT, PROJECT_REF).build();
   private static final long SOME_QG_ID = 7521551;
   private static final String SOME_QG_NAME = "name";
 
@@ -81,26 +84,24 @@ public class QualityGateMeasuresStepTest {
   public QualityGateHolderRule qualityGateHolder = new QualityGateHolderRule();
   @Rule
   public MutableQualityGateStatusHolderRule qualityGateStatusHolder = new MutableQualityGateStatusHolderRule();
+  @Rule
+  public MetricRepositoryRule metricRepository = new MetricRepositoryRule();
+  @Rule
+  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
 
-  private static final Metric ALERT_STATUS_METRIC = mock(Metric.class);
-  private static final Metric QUALITY_GATE_DETAILS_METRIC = mock(Metric.class);
-
-  private ArgumentCaptor<Measure> alertStatusMeasureCaptor = ArgumentCaptor.forClass(Measure.class);
-  private ArgumentCaptor<Measure> qgDetailsMeasureCaptor = ArgumentCaptor.forClass(Measure.class);
-
-  private MeasureRepository measureRepository = mock(MeasureRepository.class);
-  private MetricRepository metricRepository = mock(MetricRepository.class);
   private EvaluationResultTextConverter resultTextConverter = mock(EvaluationResultTextConverter.class);
   private QualityGateMeasuresStep underTest = new QualityGateMeasuresStep(treeRootHolder, qualityGateHolder, qualityGateStatusHolder, measureRepository, metricRepository,
     resultTextConverter);
 
   @Before
   public void setUp() {
+    metricRepository
+      .add(CoreMetrics.ALERT_STATUS)
+      .add(CoreMetrics.QUALITY_GATE_DETAILS)
+      .add(INT_METRIC_1)
+      .add(INT_METRIC_2);
     treeRootHolder.setRoot(PROJECT_COMPONENT);
 
-    when(metricRepository.getByKey(CoreMetrics.ALERT_STATUS_KEY)).thenReturn(ALERT_STATUS_METRIC);
-    when(metricRepository.getByKey(CoreMetrics.QUALITY_GATE_DETAILS_KEY)).thenReturn(QUALITY_GATE_DETAILS_METRIC);
-
     // mock response of asText to any argument to return the result of dumbResultTextAnswer method
     when(resultTextConverter.asText(any(Condition.class), any(EvaluationResult.class))).thenAnswer(new Answer<String>() {
       @Override
@@ -124,7 +125,7 @@ public class QualityGateMeasuresStepTest {
 
     underTest.execute();
 
-    verifyNoMoreInteractions(measureRepository);
+    measureRepository.getAddedRawMeasures(1).isEmpty();
   }
 
   @Test
@@ -133,7 +134,7 @@ public class QualityGateMeasuresStepTest {
 
     underTest.execute();
 
-    verifyNoMoreInteractions(measureRepository);
+    measureRepository.getAddedRawMeasures(PROJECT_COMPONENT).isEmpty();
   }
 
   @Test
@@ -152,19 +153,16 @@ public class QualityGateMeasuresStepTest {
   public void new_measures_are_created_even_if_there_is_no_rawMeasure_for_metric_of_condition() {
     Condition equals2Condition = createEqualsCondition(INT_METRIC_1, "2", null);
     qualityGateHolder.setQualityGate(new QualityGate(SOME_QG_ID, SOME_QG_NAME, of(equals2Condition)));
-    when(measureRepository.getRawMeasure(PROJECT_COMPONENT, INT_METRIC_1)).thenReturn(Optional.<Measure>absent());
 
     underTest.execute();
 
-    verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, INT_METRIC_1);
-    verify(measureRepository).add(same(PROJECT_COMPONENT), same(ALERT_STATUS_METRIC), alertStatusMeasureCaptor.capture());
-    verify(measureRepository).add(same(PROJECT_COMPONENT), same(QUALITY_GATE_DETAILS_METRIC), qgDetailsMeasureCaptor.capture());
-    verifyNoMoreInteractions(measureRepository);
+    Optional<Measure> addedRawMeasure = measureRepository.getAddedRawMeasure(PROJECT_COMPONENT, INT_METRIC_1_KEY);
 
-    assertThat(alertStatusMeasureCaptor.getValue())
+    assertThat(addedRawMeasure).isAbsent();
+    assertThat(getAlertStatusMeasure())
       .hasQualityGateLevel(OK)
       .hasQualityGateText("");
-    assertThat(qgDetailsMeasureCaptor.getValue())
+    assertThat(getQGDetailsMeasure())
       .hasValue(new QualityGateDetailsData(OK, Collections.<EvaluatedCondition>emptyList()).toJson());
 
     QualityGateStatusHolderAssertions.assertThat(qualityGateStatusHolder)
@@ -177,28 +175,22 @@ public class QualityGateMeasuresStepTest {
   public void rawMeasure_is_updated_if_present_and_new_measures_are_created_if_project_has_measure_for_metric_of_condition() {
     int rawValue = 1;
     Condition equals2Condition = createEqualsCondition(INT_METRIC_1, "2", null);
-    Measure rawMeasure = Measure.newMeasureBuilder().create(rawValue, null);
+    Measure rawMeasure = newMeasureBuilder().create(rawValue, null);
 
     qualityGateHolder.setQualityGate(new QualityGate(SOME_QG_ID, SOME_QG_NAME, of(equals2Condition)));
-    when(measureRepository.getRawMeasure(PROJECT_COMPONENT, INT_METRIC_1)).thenReturn(Optional.of(rawMeasure));
+    measureRepository.addRawMeasure(PROJECT_REF, INT_METRIC_1_KEY, rawMeasure);
 
     underTest.execute();
 
-    ArgumentCaptor<Measure> equals2ConditionMeasureCaptor = ArgumentCaptor.forClass(Measure.class);
+    Optional<Measure> addedRawMeasure = measureRepository.getAddedRawMeasure(PROJECT_COMPONENT, INT_METRIC_1_KEY);
 
-    verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, INT_METRIC_1);
-    verify(measureRepository).update(same(PROJECT_COMPONENT), same(INT_METRIC_1), equals2ConditionMeasureCaptor.capture());
-    verify(measureRepository).add(same(PROJECT_COMPONENT), same(ALERT_STATUS_METRIC), alertStatusMeasureCaptor.capture());
-    verify(measureRepository).add(same(PROJECT_COMPONENT), same(QUALITY_GATE_DETAILS_METRIC), qgDetailsMeasureCaptor.capture());
-    verifyNoMoreInteractions(measureRepository);
-
-    assertThat(equals2ConditionMeasureCaptor.getValue())
+    assertThat(addedRawMeasure)
       .hasQualityGateLevel(OK)
       .hasQualityGateText(dumbResultTextAnswer(equals2Condition, OK, rawValue));
-    assertThat(alertStatusMeasureCaptor.getValue())
+    assertThat(getAlertStatusMeasure())
       .hasQualityGateLevel(OK)
       .hasQualityGateText(dumbResultTextAnswer(equals2Condition, OK, rawValue));
-    assertThat(qgDetailsMeasureCaptor.getValue())
+    assertThat(getQGDetailsMeasure().get())
       .hasValue(new QualityGateDetailsData(OK, of(new EvaluatedCondition(equals2Condition, OK, rawValue))).toJson());
 
     QualityGateStatusHolderAssertions.assertThat(qualityGateStatusHolder)
@@ -212,36 +204,28 @@ public class QualityGateMeasuresStepTest {
     int rawValue = 1;
     Condition equals1ErrorCondition = createEqualsCondition(INT_METRIC_1, "1", null);
     Condition equals1WarningCondition = createEqualsCondition(INT_METRIC_2, null, "1");
-    Measure rawMeasure = Measure.newMeasureBuilder().create(rawValue, null);
+    Measure rawMeasure = newMeasureBuilder().create(rawValue, null);
 
     qualityGateHolder.setQualityGate(new QualityGate(SOME_QG_ID, SOME_QG_NAME, of(equals1ErrorCondition, equals1WarningCondition)));
-    when(measureRepository.getRawMeasure(PROJECT_COMPONENT, INT_METRIC_1)).thenReturn(Optional.of(rawMeasure));
-    when(measureRepository.getRawMeasure(PROJECT_COMPONENT, INT_METRIC_2)).thenReturn(Optional.of(rawMeasure));
+    measureRepository.addRawMeasure(PROJECT_REF, INT_METRIC_1_KEY, rawMeasure);
+    measureRepository.addRawMeasure(PROJECT_REF, INT_METRIC_2_KEY, rawMeasure);
 
     underTest.execute();
 
-    ArgumentCaptor<Measure> equals1ErrorConditionMeasureCaptor = ArgumentCaptor.forClass(Measure.class);
-    ArgumentCaptor<Measure> equals1WarningConditionMeasureCaptor = ArgumentCaptor.forClass(Measure.class);
-
-    verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, INT_METRIC_1);
-    verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, INT_METRIC_2);
-    verify(measureRepository).update(same(PROJECT_COMPONENT), same(INT_METRIC_1), equals1ErrorConditionMeasureCaptor.capture());
-    verify(measureRepository).update(same(PROJECT_COMPONENT), same(INT_METRIC_2), equals1WarningConditionMeasureCaptor.capture());
-    verify(measureRepository).add(same(PROJECT_COMPONENT), same(ALERT_STATUS_METRIC), alertStatusMeasureCaptor.capture());
-    verify(measureRepository).add(same(PROJECT_COMPONENT), same(QUALITY_GATE_DETAILS_METRIC), qgDetailsMeasureCaptor.capture());
-    verifyNoMoreInteractions(measureRepository);
+    Optional<Measure> rawMeasure1 = measureRepository.getAddedRawMeasure(PROJECT_REF, INT_METRIC_1_KEY);
+    Optional<Measure> rawMeasure2 = measureRepository.getAddedRawMeasure(PROJECT_REF, INT_METRIC_2_KEY);
 
-    assertThat(equals1ErrorConditionMeasureCaptor.getValue())
+    assertThat(rawMeasure1.get())
       .hasQualityGateLevel(ERROR)
       .hasQualityGateText(dumbResultTextAnswer(equals1ErrorCondition, ERROR, rawValue));
-    assertThat(equals1WarningConditionMeasureCaptor.getValue())
+    assertThat(rawMeasure2.get())
       .hasQualityGateLevel(WARN)
       .hasQualityGateText(dumbResultTextAnswer(equals1WarningCondition, WARN, rawValue));
-    assertThat(alertStatusMeasureCaptor.getValue())
+    assertThat(getAlertStatusMeasure())
       .hasQualityGateLevel(ERROR)
       .hasQualityGateText(dumbResultTextAnswer(equals1ErrorCondition, ERROR, rawValue) + ", "
         + dumbResultTextAnswer(equals1WarningCondition, WARN, rawValue));
-    assertThat(qgDetailsMeasureCaptor.getValue())
+    assertThat(getQGDetailsMeasure())
       .hasValue(new QualityGateDetailsData(ERROR, of(
         new EvaluatedCondition(equals1ErrorCondition, ERROR, rawValue),
         new EvaluatedCondition(equals1WarningCondition, WARN, rawValue))).toJson());
@@ -258,36 +242,28 @@ public class QualityGateMeasuresStepTest {
     int rawValue = 1;
     Condition equals2Condition = createEqualsCondition(INT_METRIC_1, "2", null);
     Condition equals1WarningCondition = createEqualsCondition(INT_METRIC_2, null, "1");
-    Measure rawMeasure = Measure.newMeasureBuilder().create(rawValue, null);
+    Measure rawMeasure = newMeasureBuilder().create(rawValue, null);
 
     qualityGateHolder.setQualityGate(new QualityGate(SOME_QG_ID, SOME_QG_NAME, of(equals2Condition, equals1WarningCondition)));
-    when(measureRepository.getRawMeasure(PROJECT_COMPONENT, INT_METRIC_1)).thenReturn(Optional.of(rawMeasure));
-    when(measureRepository.getRawMeasure(PROJECT_COMPONENT, INT_METRIC_2)).thenReturn(Optional.of(rawMeasure));
+    measureRepository.addRawMeasure(PROJECT_REF, INT_METRIC_1_KEY, rawMeasure);
+    measureRepository.addRawMeasure(PROJECT_REF, INT_METRIC_2_KEY, rawMeasure);
 
     underTest.execute();
 
-    ArgumentCaptor<Measure> equals2ConditionMeasureCaptor = ArgumentCaptor.forClass(Measure.class);
-    ArgumentCaptor<Measure> equals1WarningConditionMeasureCaptor = ArgumentCaptor.forClass(Measure.class);
-
-    verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, INT_METRIC_1);
-    verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, INT_METRIC_2);
-    verify(measureRepository).update(same(PROJECT_COMPONENT), same(INT_METRIC_1), equals2ConditionMeasureCaptor.capture());
-    verify(measureRepository).update(same(PROJECT_COMPONENT), same(INT_METRIC_2), equals1WarningConditionMeasureCaptor.capture());
-    verify(measureRepository).add(same(PROJECT_COMPONENT), same(ALERT_STATUS_METRIC), alertStatusMeasureCaptor.capture());
-    verify(measureRepository).add(same(PROJECT_COMPONENT), same(QUALITY_GATE_DETAILS_METRIC), qgDetailsMeasureCaptor.capture());
-    verifyNoMoreInteractions(measureRepository);
+    Optional<Measure> rawMeasure1 = measureRepository.getAddedRawMeasure(PROJECT_REF, INT_METRIC_1_KEY);
+    Optional<Measure> rawMeasure2 = measureRepository.getAddedRawMeasure(PROJECT_REF, INT_METRIC_2_KEY);
 
-    assertThat(equals2ConditionMeasureCaptor.getValue())
+    assertThat(rawMeasure1.get())
       .hasQualityGateLevel(OK)
       .hasQualityGateText(dumbResultTextAnswer(equals2Condition, OK, rawValue));
-    assertThat(equals1WarningConditionMeasureCaptor.getValue())
+    assertThat(rawMeasure2.get())
       .hasQualityGateLevel(WARN)
       .hasQualityGateText(dumbResultTextAnswer(equals1WarningCondition, WARN, rawValue));
-    assertThat(alertStatusMeasureCaptor.getValue())
+    assertThat(getAlertStatusMeasure())
       .hasQualityGateLevel(WARN)
       .hasQualityGateText(dumbResultTextAnswer(equals2Condition, OK, rawValue) + ", "
         + dumbResultTextAnswer(equals1WarningCondition, WARN, rawValue));
-    assertThat(qgDetailsMeasureCaptor.getValue())
+    assertThat(getQGDetailsMeasure())
       .hasValue(new QualityGateDetailsData(WARN, of(
         new EvaluatedCondition(equals2Condition, OK, rawValue),
         new EvaluatedCondition(equals1WarningCondition, WARN, rawValue))).toJson());
@@ -299,10 +275,80 @@ public class QualityGateMeasuresStepTest {
       .hasCondition(equals1WarningCondition, ConditionStatus.EvaluationStatus.WARN, String.valueOf(rawValue));
   }
 
+  @Test
+  public void new_measure_has_ERROR_level_of_all_conditions_for_a_specific_metric_if_its_the_worst() {
+    int rawValue = 1;
+    Condition fixedCondition = createEqualsCondition(INT_METRIC_1, "1", null);
+    Condition periodCondition = createEqualsCondition(INT_METRIC_1, null, "2", 1);
+
+    qualityGateHolder.setQualityGate(new QualityGate(SOME_QG_ID, SOME_QG_NAME, of(fixedCondition, periodCondition)));
+    Measure measure = newMeasureBuilder().create(rawValue, null);
+    measureRepository.addRawMeasure(PROJECT_REF, INT_METRIC_1_KEY, measure);
+
+    underTest.execute();
+
+    Optional<Measure> rawMeasure1 = measureRepository.getAddedRawMeasure(PROJECT_REF, INT_METRIC_1_KEY);
+    assertThat(rawMeasure1.get())
+      .hasQualityGateLevel(ERROR)
+      .hasQualityGateText(dumbResultTextAnswer(fixedCondition, ERROR, rawValue));
+  }
+
+  @Test
+  public void new_measure_has_WARN_level_of_all_conditions_for_a_specific_metric_if_its_the_worst() {
+    int rawValue = 2;
+    Condition fixedCondition = createEqualsCondition(INT_METRIC_1, "1", null);
+    Condition periodCondition = createEqualsCondition(INT_METRIC_1, null, "2", 1);
+
+    qualityGateHolder.setQualityGate(new QualityGate(SOME_QG_ID, SOME_QG_NAME, of(fixedCondition, periodCondition)));
+    Measure measure = newMeasureBuilder()
+      .setVariations(newMeasureVariationsBuilder().setVariation(new Period(1, "mode", null, 1212, 121), rawValue).build())
+      .create(rawValue, null);
+    measureRepository.addRawMeasure(PROJECT_REF, INT_METRIC_1_KEY, measure);
+
+    underTest.execute();
+
+    Optional<Measure> rawMeasure1 = measureRepository.getAddedRawMeasure(PROJECT_REF, INT_METRIC_1_KEY);
+    assertThat(rawMeasure1.get())
+      .hasQualityGateLevel(WARN)
+      .hasQualityGateText(dumbResultTextAnswer(periodCondition, WARN, rawValue));
+  }
+
+  @Test
+  public void new_measure_has_condition_on_leak_period_when_all_conditions_on_specific_metric_has_same_QG_level() {
+    int rawValue = 1;
+    Condition fixedCondition = createEqualsCondition(INT_METRIC_1, "1", null);
+    Condition periodCondition = createEqualsCondition(INT_METRIC_1, "1", null, 1);
+
+    qualityGateHolder.setQualityGate(new QualityGate(SOME_QG_ID, SOME_QG_NAME, of(fixedCondition, periodCondition)));
+    Measure measure = newMeasureBuilder()
+        .setVariations(newMeasureVariationsBuilder().setVariation(new Period(1, "mode", null, 1212, 121), rawValue).build())
+        .create(rawValue, null);
+    measureRepository.addRawMeasure(PROJECT_REF, INT_METRIC_1_KEY, measure);
+
+    underTest.execute();
+
+    Optional<Measure> rawMeasure1 = measureRepository.getAddedRawMeasure(PROJECT_REF, INT_METRIC_1_KEY);
+    assertThat(rawMeasure1.get())
+        .hasQualityGateLevel(ERROR)
+        .hasQualityGateText(dumbResultTextAnswer(periodCondition, ERROR, rawValue));
+  }
+
+  private Measure getAlertStatusMeasure() {
+    return measureRepository.getAddedRawMeasure(PROJECT_REF, ALERT_STATUS_KEY).get();
+  }
+
+  private Optional<Measure> getQGDetailsMeasure() {
+    return measureRepository.getAddedRawMeasure(PROJECT_REF, CoreMetrics.QUALITY_GATE_DETAILS_KEY);
+  }
+
   private static Condition createEqualsCondition(Metric metric, @Nullable String errorThreshold, @Nullable String warningThreshold) {
     return new Condition(metric, Condition.Operator.EQUALS.getDbValue(), errorThreshold, warningThreshold, null);
   }
 
+  private static Condition createEqualsCondition(Metric metric, @Nullable String errorThreshold, @Nullable String warningThreshold, @Nullable Integer period) {
+    return new Condition(metric, Condition.Operator.EQUALS.getDbValue(), errorThreshold, warningThreshold, period);
+  }
+
   private static MetricImpl createIntMetric(int index) {
     return new MetricImpl(index, "metricKey" + index, "metricName" + index, Metric.MetricType.INT);
   }