Skip to content
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
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.xmlunit</groupId>
<artifactId>xmlunit-core</artifactId>
<version>2.11.0</version>
<scope>test</scope>
</dependency>
</dependencies>

<repositories>
Expand Down
113 changes: 113 additions & 0 deletions src/main/java/hudson/tasks/junit/CaseResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@
private String errorStackTrace;
private String errorDetails;
private Map<String, String> properties;
private List<Failure> flakyFailures;
private List<Failure> rerunFailures;

@SuppressFBWarnings(value = "SE_TRANSIENT_FIELD_NOT_RESTORED", justification = "Specific method to restore it")
private transient SuiteResult parent;
Expand Down Expand Up @@ -247,6 +249,8 @@
}
this.properties = properties;
this.keepTestNames = keepTestNames;
this.flakyFailures = parseFlakyFailures(testCase);
this.rerunFailures = parseRerunFailures(testCase);
}

public CaseResult(CaseResult src) {
Expand All @@ -263,12 +267,46 @@
this.stderr = src.stderr;
this.properties = new HashMap<>();
this.properties.putAll(src.properties);
this.flakyFailures = src.flakyFailures;
this.rerunFailures = src.rerunFailures;
}

public static float clampDuration(float d) {
return Math.min(365.0f * 24 * 60 * 60, Math.max(0.0f, d));
}

private static List<Failure> parseFlakyFailures(Element testCase) {
List<Failure> failures = new ArrayList<>();
List<Element> flakyFailuresElements = testCase.elements("flakyFailure");
if (flakyFailuresElements != null) {

Check warning on line 281 in src/main/java/hudson/tasks/junit/CaseResult.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 281 is only partially covered, one branch is missing
for (Element flakyFailuresElement : flakyFailuresElements) {
String message = flakyFailuresElement.attributeValue("message");
String type = flakyFailuresElement.attributeValue("type");
String stackTrace = flakyFailuresElement.elementText("stackTrace");
String stdout = flakyFailuresElement.elementText("system-out");
String stderr = flakyFailuresElement.elementText("system-err");
failures.add(new Failure(message, type, stackTrace, stdout, stderr));
}
}
return failures;
}

private static List<Failure> parseRerunFailures(Element testCase) {
List<Failure> rerunFailures = new ArrayList<>();
List<Element> rerunFailureElements = testCase.elements("rerunFailure");
if (rerunFailureElements != null) {

Check warning on line 297 in src/main/java/hudson/tasks/junit/CaseResult.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 297 is only partially covered, one branch is missing
for (Element rerunFailureElement : rerunFailureElements) {
String message = rerunFailureElement.attributeValue("message");
String type = rerunFailureElement.attributeValue("type");
String stackTrace = rerunFailureElement.elementText("stackTrace");
String stdout = rerunFailureElement.elementText("system-out");
String stderr = rerunFailureElement.elementText("system-err");
rerunFailures.add(new Failure(message, type, stackTrace, stdout, stderr));
}
}
return rerunFailures;
}

static CaseResult parse(SuiteResult parent, final XMLStreamReader reader, String context, String ver)
throws XMLStreamException {
CaseResult r = new CaseResult(parent, null, null, null);
Expand Down Expand Up @@ -320,6 +358,12 @@
r.properties = new HashMap<>();
parseProperties(r.properties, reader, context, ver);
break;
case "flakyFailures":
r.flakyFailures = parseFailures(reader, context, "flakyFailures");
break;
case "rerunFailures":
r.rerunFailures = parseFailures(reader, context, "rerunFailures");
break;
default:
LOGGER.finest(() -> "Unknown field in " + context + ": " + elementName);
}
Expand All @@ -328,6 +372,63 @@
return r;
}

static List<Failure> parseFailures(final XMLStreamReader reader, String context, String endElement)
throws XMLStreamException {
List<Failure> failures = new ArrayList<>();
while (reader.hasNext()) {

Check warning on line 378 in src/main/java/hudson/tasks/junit/CaseResult.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 378 is only partially covered, one branch is missing
final int event = reader.next();
if (event == XMLStreamReader.END_ELEMENT && reader.getLocalName().equals(endElement)) {

Check warning on line 380 in src/main/java/hudson/tasks/junit/CaseResult.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 380 is only partially covered, one branch is missing
break;
}
if (event == XMLStreamReader.START_ELEMENT) {
final String elementName = reader.getLocalName();
if (elementName.equals("failure")) {

Check warning on line 385 in src/main/java/hudson/tasks/junit/CaseResult.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 385 is only partially covered, one branch is missing
failures.add(parseFailure(reader, context));
} else {
LOGGER.finest(() -> "Unknown field in " + context + ": " + elementName);

Check warning on line 388 in src/main/java/hudson/tasks/junit/CaseResult.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 388 is not covered by tests
}
}
}
return failures;
}

public static Failure parseFailure(XMLStreamReader reader, String context) throws XMLStreamException {
String message = null;
String type = null;
String stackTrace = null;
String stdout = null;
String stderr = null;
while (reader.hasNext()) {

Check warning on line 401 in src/main/java/hudson/tasks/junit/CaseResult.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 401 is only partially covered, one branch is missing
int event = reader.next();
if (event == XMLStreamReader.END_ELEMENT && "failure".equals(reader.getLocalName())) {

Check warning on line 403 in src/main/java/hudson/tasks/junit/CaseResult.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 403 is only partially covered, one branch is missing
break;
}
if (event == XMLStreamReader.START_ELEMENT) {
String elementName = reader.getLocalName();
switch (elementName) {

Check warning on line 408 in src/main/java/hudson/tasks/junit/CaseResult.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 408 is only partially covered, one branch is missing
case "message":
message = reader.getElementText();
break;
case "type":
type = reader.getElementText();
break;
case "stackTrace":
stackTrace = reader.getElementText();
break;
case "stdout":
stdout = reader.getElementText();
break;
case "stderr":
stderr = reader.getElementText();
break;
default:
LOGGER.finest(() -> "Unknown field in " + context + ": " + elementName);

Check warning on line 425 in src/main/java/hudson/tasks/junit/CaseResult.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 425 is not covered by tests
}
}
}
return new Failure(message, type, stackTrace, stdout, stderr);
}

static void parseProperties(Map<String, String> r, final XMLStreamReader reader, String context, String ver)
throws XMLStreamException {
while (reader.hasNext()) {
Expand Down Expand Up @@ -1040,6 +1141,18 @@
this.parent = parent;
}

@Exported
@Override
public List<Failure> getFlakyFailures() {
return flakyFailures == null ? Collections.emptyList() : Collections.unmodifiableList(flakyFailures);
}

@Exported
@Override
public List<Failure> getRerunFailures() {
return rerunFailures == null ? Collections.emptyList() : Collections.unmodifiableList(rerunFailures);
}

/**
* Constants that represent the status of this test.
*/
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/hudson/tasks/junit/Failure.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package hudson.tasks.junit;

import java.io.Serializable;
import org.kohsuke.stapler.export.ExportedBean;

@ExportedBean
public record Failure(String message, String type, String stackTrace, String stdout, String stderr)
implements Serializable {}
1 change: 1 addition & 0 deletions src/main/java/hudson/tasks/junit/TestResultAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ public Widget getWidget() {
XSTREAM.alias("result", TestResult.class);
XSTREAM.alias("suite", SuiteResult.class);
XSTREAM.alias("case", CaseResult.class);
XSTREAM.alias("failure", Failure.class);
XSTREAM.registerConverter(new HeapSpaceStringConverter(), 100);
}
}
10 changes: 10 additions & 0 deletions src/main/java/hudson/tasks/test/TestResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
import hudson.model.Job;
import hudson.model.Result;
import hudson.model.Run;
import hudson.tasks.junit.Failure;
import hudson.tasks.junit.TestAction;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand Down Expand Up @@ -263,6 +265,14 @@
return Collections.emptyMap();
}

public List<Failure> getFlakyFailures() {
return Collections.emptyList();
}

public List<Failure> getRerunFailures() {
return Collections.emptyList();

Check warning on line 273 in src/main/java/hudson/tasks/test/TestResult.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 269-273 are not covered by tests
}

/**
* @return true if the test was not skipped and did not fail, false otherwise.
*/
Expand Down
Loading
Loading