Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not convert complexity density into a percentage #186

Merged
merged 1 commit into from
Jul 1, 2024
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 @@ -31,6 +31,7 @@
* @author Florian Orendi
*/
// TODO: create instances for the different types
// TODO: rethink the approach of storing the delta values as FractionValues

Check warning on line 34 in plugin/src/main/java/io/jenkins/plugins/coverage/metrics/model/ElementFormatter.java

View check run for this annotation

ci.jenkins.io / Open Tasks Scanner

TODO

NORMAL: rethink the approach of storing the delta values as FractionValues
@SuppressWarnings({"PMD.GodClass", "PMD.CyclomaticComplexity"})
public final class ElementFormatter {
private static final Fraction HUNDRED = Fraction.getFraction("100.0");
Expand All @@ -51,7 +52,11 @@
if (value instanceof IntegerValue) {
return String.format("%s: %d", getLabel(value.getMetric()), ((IntegerValue) value).getValue());
}
return formatValueWithMetric(value) + " (" + formatAdditionalInformation(value) + ")";
var additional = formatAdditionalInformation(value);
if (additional.isBlank()) {
return formatValueWithMetric(value);
}
return formatValueWithMetric(value) + " (" + additional + ")";
}

/**
Expand Down Expand Up @@ -88,7 +93,10 @@
return String.valueOf(((IntegerValue) value).getValue());
}
if (value instanceof FractionValue) {
return formatDelta(((FractionValue) value).getFraction(), value.getMetric(), locale);
if (value.getMetric() == Metric.COMPLEXITY_DENSITY) {
return String.format(locale, "%.2f", ((FractionValue) value).getFraction().doubleValue());
}
return formatDelta(value.getMetric(), ((FractionValue) value).getFraction(), locale);
}
return value.toString();
}
Expand Down Expand Up @@ -119,7 +127,7 @@
*
* @return the formatted value as plain text
*/
public String formatDetails(final Value value, final Locale locale) {
private String formatDetails(final Value value, final Locale locale) {
if (value instanceof Coverage) {
var coverage = (Coverage) value;
return formatPercentage(coverage, locale)
Expand All @@ -129,6 +137,9 @@
return String.valueOf(((IntegerValue) value).getValue());
}
if (value instanceof FractionValue) {
if (value.getMetric() == Metric.COMPLEXITY_DENSITY) {
return String.format(locale, "%.2f", ((FractionValue) value).getFraction().doubleValue());
}
return String.format(locale, "%.2f%%", ((FractionValue) value).getFraction().doubleValue());
}
return value.toString();
Expand Down Expand Up @@ -210,7 +221,6 @@
*
* @return the value formatted as a string
*/
@SuppressWarnings("unused") // Called by jelly view
public String formatValue(final Value value) {
return formatDetails(value, Functions.getCurrentLocale());
}
Expand Down Expand Up @@ -337,22 +347,25 @@
* Formats a delta percentage to its plain text representation with a leading sign and rounds the value to two
* decimals.
*
* @param fraction
* the value of the delta
* @param metric
* the metric of the value
* @param fraction
* the value of the delta
* @param locale
* the locale to use to render the values
*
* @return the formatted delta percentage as plain text with a leading sign
*/
public String formatDelta(final Fraction fraction, final Metric metric, final Locale locale) {
public String formatDelta(final Metric metric, final Fraction fraction, final Locale locale) {
if (metric.equals(Metric.COMPLEXITY)
|| metric.equals(Metric.COMPLEXITY_MAXIMUM)
|| metric.equals(Metric.LOC)
|| metric.equals(Metric.TESTS)) {
return String.format(locale, "%+d", fraction.intValue());
}
if (metric == Metric.COMPLEXITY_DENSITY) {
return String.format(locale, "%+.2f", fraction.doubleValue());
}
return String.format(locale, "%+.2f%%", new SafeFraction(fraction).multiplyBy(HUNDRED).doubleValue());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,13 +524,13 @@ public String formatValue(final Baseline baseline, final Metric metric) {
public String formatDelta(final Baseline baseline, final Metric metric) {
var currentLocale = Functions.getCurrentLocale();
if (baseline == Baseline.PROJECT && hasDelta(baseline, metric)) {
return FORMATTER.formatDelta(difference.get(metric), metric, currentLocale);
return FORMATTER.formatDelta(metric, difference.get(metric), currentLocale);
}
if (baseline == Baseline.MODIFIED_LINES && hasDelta(baseline, metric)) {
return FORMATTER.formatDelta(modifiedLinesCoverageDifference.get(metric), metric, currentLocale);
return FORMATTER.formatDelta(metric, modifiedLinesCoverageDifference.get(metric), currentLocale);
}
if (baseline == Baseline.MODIFIED_FILES && hasDelta(baseline, metric)) {
return FORMATTER.formatDelta(modifiedFilesCoverageDifference.get(metric), metric, currentLocale);
return FORMATTER.formatDelta(metric, modifiedFilesCoverageDifference.get(metric), currentLocale);
}
return Messages.Coverage_Not_Available();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@
*/
@SuppressWarnings("unused") // Called by jelly view
public String formatValue(final Value value) {
return FORMATTER.formatDetails(value, Functions.getCurrentLocale());
return FORMATTER.formatValue(value);

Check warning on line 135 in plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageMetricColumn.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 135 is not covered by tests
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.Locale;
import java.util.stream.Collectors;

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

import edu.hm.hafner.coverage.Coverage;
Expand Down Expand Up @@ -35,7 +36,6 @@
import io.jenkins.plugins.datatables.TableConfiguration;
import io.jenkins.plugins.datatables.TableConfiguration.SelectStyle;
import io.jenkins.plugins.datatables.TableModel;
import org.apache.commons.lang3.StringUtils;

import static j2html.TagCreator.*;

Expand Down Expand Up @@ -119,11 +119,11 @@
Messages.Column_DeltaLineCoverage("Δ"), columns);
configureValueColumn("branchCoverage", Metric.BRANCH, Messages.Column_BranchCoverage(),
Messages.Column_DeltaBranchCoverage("Δ"), columns);

/* VectorCAST metrics */
configureValueColumn("mcdcPairCoverage", Metric.MCDC_PAIR, Messages.Column_MCDCPairs(),
configureValueColumn("mcdcPairCoverage", Metric.MCDC_PAIR, Messages.Column_MCDCPairs(),
"", columns);
configureValueColumn("functionCallCoverage", Metric.FUNCTION_CALL, Messages.Column_FunctionCall(),
configureValueColumn("functionCallCoverage", Metric.FUNCTION_CALL, Messages.Column_FunctionCall(),
"", columns);

configureValueColumn("mutationCoverage", Metric.MUTATION, Messages.Column_MutationCoverage(),
Expand Down Expand Up @@ -370,7 +370,7 @@
div().withClasses(COVERAGE_COLUMN_INNER)
.withStyle(String.format("background-color:%s;", colors.getFillColorAsRGBAHex(
TABLE_COVERAGE_COLOR_ALPHA)))
.withText(FORMATTER.formatDelta(delta, metric, browserLocale)))
.withText(FORMATTER.formatDelta(metric, delta, browserLocale)))

Check warning on line 373 in plugin/src/main/java/io/jenkins/plugins/coverage/metrics/steps/CoverageTableModel.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 373 is not covered by tests
.render();
return new DetailedCell<>(cell, percentage);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,103 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junitpioneer.jupiter.DefaultLocale;

import edu.hm.hafner.coverage.Coverage;
import edu.hm.hafner.coverage.Coverage.CoverageBuilder;
import edu.hm.hafner.coverage.FractionValue;
import edu.hm.hafner.coverage.LinesOfCode;
import edu.hm.hafner.coverage.Metric;

import static org.assertj.core.api.Assertions.*;

@DefaultLocale("en")
class ElementFormatterTest {
@Test
void shouldFormatTooltip() {
var formatter = new ElementFormatter();

var density = new FractionValue(Metric.COMPLEXITY_DENSITY, 33, 100);
assertThat(formatter.getTooltip(density)).isEqualTo("Complexity Density: 0.33");
assertThat(formatter.formatValueWithMetric(density)).isEqualTo("Complexity Density: 0.33");
assertThat(formatter.formatDetailedValueWithMetric(density)).isEqualTo("Complexity Density: 0.33");
assertThat(formatter.format(density)).isEqualTo("0.33");
assertThat(formatter.formatDetails(density)).isEqualTo("0.33");
assertThat(formatter.formatValue(density)).isEqualTo("0.33");
assertThat(formatter.formatAdditionalInformation(density)).isEmpty();

var loc = new LinesOfCode(123);
assertThat(formatter.getTooltip(loc)).isEqualTo("LOC: 123");
assertThat(formatter.formatValueWithMetric(loc)).isEqualTo("Lines of Code: 123");
assertThat(formatter.formatDetailedValueWithMetric(loc)).isEqualTo("Lines of Code: 123");
assertThat(formatter.format(loc)).isEqualTo("123");
assertThat(formatter.formatDetails(loc)).isEqualTo("123");
assertThat(formatter.formatValue(loc)).isEqualTo("123");
assertThat(formatter.formatAdditionalInformation(loc)).isEmpty();

var empty = Coverage.nullObject(Metric.BRANCH);
assertThat(formatter.getTooltip(empty)).isEqualTo("Branch Coverage: -");
assertThat(formatter.formatValueWithMetric(empty)).isEqualTo("Branch Coverage: -");
assertThat(formatter.formatDetailedValueWithMetric(empty)).isEqualTo("Branch Coverage: -");
assertThat(formatter.format(empty)).isEqualTo("-");
assertThat(formatter.formatPercentage(empty, Locale.ENGLISH)).isEqualTo("-");
assertThat(formatter.formatDetails(empty)).isEqualTo("-");
assertThat(formatter.formatValue(empty)).isEqualTo("-");
assertThat(formatter.formatAdditionalInformation(empty)).isEmpty();

var line = new CoverageBuilder(Metric.LINE).withCovered(3).withMissed(1).build();
assertThat(formatter.getTooltip(line)).isEqualTo("Line Coverage: 75.00% (Covered: 3 - Missed: 1)");
assertThat(formatter.formatValueWithMetric(line)).isEqualTo("Line Coverage: 75.00%");
assertThat(formatter.formatDetailedValueWithMetric(line)).isEqualTo("Line Coverage: 75.00% (3/4)");
assertThat(formatter.format(line)).isEqualTo("75.00%");
assertThat(formatter.formatPercentage(line, Locale.ENGLISH)).isEqualTo("75.00%");
assertThat(formatter.formatDetails(line)).isEqualTo("75.00% (3/4)");
assertThat(formatter.formatValue(line)).isEqualTo("75.00% (3/4)");
assertThat(formatter.formatAdditionalInformation(line)).isEqualTo("Covered: 3 - Missed: 1");

var mutation = new CoverageBuilder(Metric.MUTATION).withCovered(3).withMissed(1).build();
assertThat(formatter.getTooltip(mutation)).isEqualTo("Mutation Coverage: 75.00% (Killed: 3 - Survived: 1)");
assertThat(formatter.formatValueWithMetric(mutation)).isEqualTo("Mutation Coverage: 75.00%");
assertThat(formatter.formatDetailedValueWithMetric(mutation)).isEqualTo("Mutation Coverage: 75.00% (3/4)");
assertThat(formatter.format(mutation)).isEqualTo("75.00%");
assertThat(formatter.formatPercentage(mutation, Locale.ENGLISH)).isEqualTo("75.00%");
assertThat(formatter.formatDetails(mutation)).isEqualTo("75.00% (3/4)");
assertThat(formatter.formatValue(mutation)).isEqualTo("75.00% (3/4)");
assertThat(formatter.formatAdditionalInformation(mutation)).isEqualTo("Killed: 3 - Survived: 1");

var delta = new FractionValue(Metric.FILE, -1, 5);
// These do not make sense when the fraction represents a delta
// assertThat(formatter.getTooltip(delta)).isEqualTo("File Coverage: -20.00%");
// assertThat(formatter.formatValueWithMetric(delta)).isEqualTo("File Coverage: -20.00%");
// assertThat(formatter.format(delta)).isEqualTo("-20.00%");
assertThat(formatter.formatDetailedValueWithMetric(delta)).isEqualTo("File Coverage: -0.20%");
assertThat(formatter.formatDetails(delta)).isEqualTo("-0.20%");
assertThat(formatter.formatValue(delta)).isEqualTo("-0.20%");
assertThat(formatter.formatAdditionalInformation(delta)).isEmpty();
}

@Test
void shouldHandleOverflowGracefully() {
var formatter = new ElementFormatter();

var fraction = Fraction.getFraction(Integer.MAX_VALUE - 1, Integer.MAX_VALUE - 1);
var delta = formatter.formatDelta(fraction, Metric.LINE, Locale.ENGLISH);
var delta = formatter.formatDelta(Metric.LINE, fraction, Locale.ENGLISH);

assertThat(delta).isEqualTo("+100.00%");
}

@Test
void shouldFormatDelta() {
var formatter = new ElementFormatter();

assertThat(formatter.formatDelta(Metric.LINE, Fraction.getFraction(-1, 1),
Locale.ENGLISH)).isEqualTo("-100.00%");
assertThat(formatter.formatDelta(Metric.LOC, Fraction.getFraction(-1, 1),
Locale.ENGLISH)).isEqualTo("-1");
assertThat(formatter.formatDelta(Metric.COMPLEXITY_DENSITY, Fraction.getFraction(-1, 1),
Locale.ENGLISH)).isEqualTo("-1.00");
}

@ParameterizedTest
@EnumSource(value = Metric.class, mode = EnumSource.Mode.EXCLUDE, names = {"CONTAINER", "COMPLEXITY_DENSITY"})
void shouldSupportAllMetrics(final Metric metric) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void shouldProvideRemoteApi() {
.node("projectStatistics").isEqualTo("{\n"
+ " \"branch\": \"88.28%\",\n"
+ " \"complexity\": \"2558\",\n"
+ " \"complexity-density\": \"+44.12%\",\n"
+ " \"complexity-density\": \"0.44\",\n"
+ " \"complexity-maximum\": \"21\",\n"
+ " \"file\": \"99.67%\",\n"
+ " \"instruction\": \"96.11%\",\n"
Expand Down Expand Up @@ -93,7 +93,7 @@ void shouldShowDeltaInRemoteApi() {
.node("projectDelta").isEqualTo("{\n"
+ " \"branch\": \"+5.33%\",\n"
+ " \"complexity\": \"-2558\",\n"
+ " \"complexity-density\": \"+5.13%\",\n"
+ " \"complexity-density\": \"0.05\",\n"
+ " \"complexity-maximum\": \"-15\",\n"
+ " \"file\": \"-28.74%\",\n"
+ " \"instruction\": \"-2.63%\",\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
No changes detected, that affect the code coverage.
* Line Coverage: 91.02% (294/323)
* Branch Coverage: 93.97% (109/116)
* Complexity Density: 0.50%
* Complexity Density: 0.50
* Lines of Code: 323
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* **[Overall project (difference to reference job)](http://127.0.0.1:8080/job/pipeline-coding-style/job/5/coverage#overview)**
* Line Coverage: 91.02% (294/323) - Delta: +50.00%
* Branch Coverage: 93.97% (109/116)
* Complexity Density: 0.50%
* Complexity Density: 0.50
* Lines of Code: 323
* **[Modified files (difference to reference job)](http://127.0.0.1:8080/job/pipeline-coding-style/job/5/coverage#modifiedFilesCoverage)**
* Line Coverage: 50.00% (1/2) - Delta: +50.00%
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ No changes detected, that affect the code coverage.
* Branch Coverage: 66.18% (180/272)
* MC/DC Pair Coverage: 40.68% (24/59)
* Function Call Coverage: 78.48% (62/79)
* Complexity Density: 0.34%
* Complexity Density: 0.34
* Lines of Code: 294

#### Quality Gates Summary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
No changes detected, that affect the code coverage.
* Line Coverage: 65.00% (52/80)
* Branch Coverage: 67.65% (23/34)
* Complexity Density: 0.31%
* Complexity Density: 0.31
* Lines of Code: 80

#### Quality Gates Summary

No active quality gates.
No active quality gates.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ No changes detected, that affect the code coverage.
* Branch Coverage: 66.18% (180/272)
* MC/DC Pair Coverage: 40.68% (24/59)
* Function Call Coverage: 78.48% (62/79)
* Complexity Density: 0.34%
* Complexity Density: 0.34
* Lines of Code: 294

#### Quality Gates Summary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ No changes detected, that affect the code coverage.
* Line Coverage: 65.22% (45/69)
* Branch Coverage: 71.43% (20/28)
* MC/DC Pair Coverage: 66.67% (8/12)
* Complexity Density: 0.36%
* Complexity Density: 0.36
* Lines of Code: 69

#### Quality Gates Summary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* **[Overall project (difference to reference job)](http://127.0.0.1:8080/job/pipeline-coding-style/job/5/coverage#overview)**
* Line Coverage: 91.02% (294/323) - Delta: +50.00%
* Branch Coverage: 93.97% (109/116)
* Complexity Density: 0.50%
* Complexity Density: 0.50
* Lines of Code: 323
* **[Modified files (difference to reference job)](http://127.0.0.1:8080/job/pipeline-coding-style/job/5/coverage#modifiedFilesCoverage)**
* Line Coverage: 50.00% (1/2) - Delta: +50.00%
Expand Down
Loading