Skip to content

Commit

Permalink
Do not convert complexity density into a percentage.
Browse files Browse the repository at this point in the history
The density should be reported as a float value.
  • Loading branch information
uhafner committed Jun 30, 2024
1 parent 7f603f3 commit d1302cf
Show file tree
Hide file tree
Showing 13 changed files with 120 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ public String getTooltip(final Value value) {
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 +92,10 @@ public String format(final Value value, final Locale locale) {
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 +126,7 @@ public String formatDetails(final Value value) {
*
* @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 +136,9 @@ public String formatDetails(final Value value, final Locale locale) {
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 +220,6 @@ else if (value instanceof FractionValue) {
*
* @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 +346,25 @@ public String formatPercentage(final int covered, final int total, final Locale
* 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 @@ public String formatMetric(final Value value) {
*/
@SuppressWarnings("unused") // Called by jelly view
public String formatValue(final Value value) {
return FORMATTER.formatDetails(value, Functions.getCurrentLocale());
return FORMATTER.formatValue(value);
}

/**
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 @@ public List<TableColumn> getColumns() {
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 @@ protected DetailedCell<?> createColoredCoverageDeltaColumn(final Metric metric,
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)))
.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

0 comments on commit d1302cf

Please sign in to comment.