Skip to content
This repository was archived by the owner on Nov 19, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
import java.util.Collection;
import java.util.Locale;

import org.apache.commons.lang3.math.Fraction;

import edu.hm.hafner.coverage.FractionValue;
import edu.hm.hafner.coverage.Metric;
import edu.hm.hafner.coverage.SafeFraction;
import edu.hm.hafner.coverage.Value;

import io.jenkins.plugins.coverage.metrics.model.CoverageStatistics;
import io.jenkins.plugins.coverage.metrics.model.ElementFormatter;
import io.jenkins.plugins.util.QualityGateEvaluator;
Expand All @@ -15,10 +22,13 @@
* @author Johannes Walter
*/
class CoverageQualityGateEvaluator extends QualityGateEvaluator<CoverageQualityGate> {
private static final Fraction HUNDRED = Fraction.getFraction("100.0");

private static final ElementFormatter FORMATTER = new ElementFormatter();
private final CoverageStatistics statistics;

CoverageQualityGateEvaluator(final Collection<? extends CoverageQualityGate> qualityGates, final CoverageStatistics statistics) {
CoverageQualityGateEvaluator(final Collection<? extends CoverageQualityGate> qualityGates,
final CoverageStatistics statistics) {
super(qualityGates);

this.statistics = statistics;
Expand All @@ -29,14 +39,41 @@ protected void evaluate(final CoverageQualityGate qualityGate, final QualityGate
var baseline = qualityGate.getBaseline();
var possibleValue = statistics.getValue(baseline, qualityGate.getMetric());
if (possibleValue.isPresent()) {
var actualValue = possibleValue.get();
var actualValue = convertActualValue(possibleValue.get());

var status = actualValue.isOutOfValidRange(
qualityGate.getThreshold()) ? qualityGate.getStatus() : QualityGateStatus.PASSED;
result.add(qualityGate, status, FORMATTER.format(actualValue, Locale.ENGLISH));
result.add(qualityGate, status, FORMATTER.format(possibleValue.get(), Locale.ENGLISH));
}
else {
result.add(qualityGate, QualityGateStatus.INACTIVE, "n/a");
}
}

/**
* Converts the actual value to a percentage if necessary. Delta values are internally stored as fractions, but
* users expect percentages when they are displayed or used in thresholds.
*
* @param value
* the actual stored value
*
* @return the converted value
*/
private Value convertActualValue(final Value value) {
var metric = value.getMetric();
if (metric.equals(Metric.COMPLEXITY)
|| metric.equals(Metric.COMPLEXITY_MAXIMUM)
|| metric.equals(Metric.LOC)) {
return value; // ignore integer based metrics
}
if (value instanceof FractionValue) { // delta percentage
return new FractionValue(metric, covertToPercentage((FractionValue) value));
}

return value;
}

private Fraction covertToPercentage(final FractionValue value) {
return new SafeFraction(value.getFraction()).multiplyBy(HUNDRED);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.util.List;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import edu.hm.hafner.coverage.Metric;

Expand Down Expand Up @@ -137,6 +139,51 @@ void shouldReportUnstableIfWorseAndSuccessIfBetter() {
"-> [Modified files (difference to overall project) - Line Coverage]: ≪Success≫ - (Actual value: +5.00%, Quality gate: 0.00)");
}

@ParameterizedTest(name = "A quality gate of {0} should not be passed if the coverage drops by 10%")
@ValueSource(ints = {8, 1, 0, -1, -8})
void shouldHandleNegativeValues(final double minimum) {
Collection<CoverageQualityGate> qualityGates = new ArrayList<>();

qualityGates.add(new CoverageQualityGate(minimum, Metric.FILE, Baseline.PROJECT_DELTA, QualityGateCriticality.UNSTABLE));

CoverageQualityGateEvaluator evaluator = new CoverageQualityGateEvaluator(qualityGates, createStatistics());
QualityGateResult result = evaluator.evaluate();

assertThat(result).hasOverallStatus(QualityGateStatus.WARNING).isNotSuccessful().isNotInactive().hasMessages(
String.format(
"-> [Overall project (difference to reference job) - File Coverage]: ≪Unstable≫ - (Actual value: -10.00%%, Quality gate: %.2f)", minimum));
}

@ParameterizedTest(name = "A quality gate of {0} should be passed if the coverage is at 50%")
@ValueSource(ints = {-10, 0, 10, 50})
void shouldPassAllThresholds(final double minimum) {
Collection<CoverageQualityGate> qualityGates = new ArrayList<>();

qualityGates.add(new CoverageQualityGate(minimum, Metric.LINE, Baseline.PROJECT, QualityGateCriticality.UNSTABLE));

CoverageQualityGateEvaluator evaluator = new CoverageQualityGateEvaluator(qualityGates, createStatistics());
QualityGateResult result = evaluator.evaluate();

assertThat(result).hasOverallStatus(QualityGateStatus.PASSED).isSuccessful().isNotInactive().hasMessages(
String.format(
"-> [Overall project - Line Coverage]: ≪Success≫ - (Actual value: 50.00%%, Quality gate: %.2f)", minimum));
}

@ParameterizedTest(name = "A quality gate of {0} should not be passed if the coverage is at 50%")
@ValueSource(ints = {51, 60, 70, 200})
void shouldFailAllThresholds(final double minimum) {
Collection<CoverageQualityGate> qualityGates = new ArrayList<>();

qualityGates.add(new CoverageQualityGate(minimum, Metric.LINE, Baseline.PROJECT, QualityGateCriticality.UNSTABLE));

CoverageQualityGateEvaluator evaluator = new CoverageQualityGateEvaluator(qualityGates, createStatistics());
QualityGateResult result = evaluator.evaluate();

assertThat(result).hasOverallStatus(QualityGateStatus.WARNING).isNotSuccessful().isNotInactive().hasMessages(
String.format(
"-> [Overall project - Line Coverage]: ≪Unstable≫ - (Actual value: 50.00%%, Quality gate: %.2f)", minimum));
}

@Test
void shouldReportUnstableIfLargerThanThreshold() {
Collection<CoverageQualityGate> qualityGates = new ArrayList<>();
Expand All @@ -155,7 +202,7 @@ void shouldReportUnstableIfLargerThanThreshold() {
}

@Test
void shouldReportUnstableIfWorseAndSuccessIfBetter2() {
void shouldReportUnstableIfWorseAndSuccessIfLargerThanThreshold() {
Collection<CoverageQualityGate> qualityGates = new ArrayList<>();

var minimum = 0;
Expand Down