diff --git a/.gitlab/collect-result/JUnitReport.java b/.gitlab/collect-result/JUnitReport.java index b9f8dad568b..3791103c0c8 100644 --- a/.gitlab/collect-result/JUnitReport.java +++ b/.gitlab/collect-result/JUnitReport.java @@ -114,6 +114,32 @@ void tagSyntheticFailures() { } } + /// Tags non-final attempts of a retried test so Test Optimization does not surface them as + /// real failures. The Develocity testRetry plugin re-runs failed tests and emits one + /// `` per attempt sharing the same `(classname, name)`; CI ignores all but the + /// final attempt, so this method does the same by marking earlier attempts as `skip`. + /// + /// Must run before [#tagFinalStatuses] so the existing per-testcase tagger does not + /// overwrite `skip` with `fail`. + /// + /// See https://docs.gradle.com/develocity/gradle-plugin/current/#test_retry + void tagRetriedTests() { + var all = testcases(); + for (var i = 0; i < all.size(); i++) { + var current = all.get(i); + var classname = current.getAttribute("classname"); + var name = current.getAttribute("name"); + for (var j = i + 1; j < all.size(); j++) { + var later = all.get(j); + if (classname.equals(later.getAttribute("classname")) + && name.equals(later.getAttribute("name"))) { + addFinalStatusProperty(current, "skip", MissingPropertiesPlacement.APPEND_TO_TESTCASE); + break; + } + } + } + } + void tagFinalStatuses() { for (var testcase : testcases()) { if (hasFinalStatusProperty(testcase)) { diff --git a/.gitlab/collect-result/ResultCollector.java b/.gitlab/collect-result/ResultCollector.java index d993cd41d32..ee5240df278 100644 --- a/.gitlab/collect-result/ResultCollector.java +++ b/.gitlab/collect-result/ResultCollector.java @@ -48,6 +48,7 @@ private void collect(Path sourceXml) throws Exception { var reportChangedBeforeFinalStatus = report.addFileAttribute(sourceFile); reportChangedBeforeFinalStatus |= report.normalizeStableTestNames(); report.tagSyntheticFailures(); + report.tagRetriedTests(); report.tagFinalStatuses(); report.write(targetXml);