app.getxray.xray.junit.customjunitxml.XmlReportData Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xray-junit-extensions Show documentation
Show all versions of xray-junit-extensions Show documentation
Improvements for JUnit that allow you to take better advantage of JUnit 5 (jupiter engine) whenever using it together with Xray Test Management.
The newest version!
/*
* Copyright 2015-2021 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package app.getxray.xray.junit.customjunitxml;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;
import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import org.junit.platform.commons.util.ExceptionUtils;
import org.junit.platform.engine.TestExecutionResult;
import org.junit.platform.engine.reporting.ReportEntry;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
class XmlReportData {
private final Map finishedTests = new ConcurrentHashMap<>();
private final Map skippedTests = new ConcurrentHashMap<>();
private final Map startInstants = new ConcurrentHashMap<>();
private final Map endInstants = new ConcurrentHashMap<>();
private final Map> reportEntries = new ConcurrentHashMap<>();
private final TestPlan testPlan;
private final Clock clock;
XmlReportData(TestPlan testPlan, Clock clock) {
this.testPlan = testPlan;
this.clock = clock;
}
TestPlan getTestPlan() {
return this.testPlan;
}
Clock getClock() {
return this.clock;
}
void markSkipped(TestIdentifier testIdentifier, String reason) {
this.skippedTests.put(testIdentifier, reason == null ? "" : reason);
}
void markStarted(TestIdentifier testIdentifier) {
this.startInstants.put(testIdentifier, this.clock.instant());
}
void markFinished(TestIdentifier testIdentifier, TestExecutionResult result) {
this.endInstants.put(testIdentifier, this.clock.instant());
if (result.getStatus() == ABORTED) {
String reason = result.getThrowable().map(ExceptionUtils::readStackTrace).orElse("");
this.skippedTests.put(testIdentifier, reason);
} else {
this.finishedTests.put(testIdentifier, result);
}
}
void addReportEntry(TestIdentifier testIdentifier, ReportEntry entry) {
List entries = this.reportEntries.computeIfAbsent(testIdentifier, key -> new ArrayList<>());
entries.add(entry);
}
boolean wasSkipped(TestIdentifier testIdentifier) {
return findSkippedAncestor(testIdentifier).isPresent();
}
double getDurationInSeconds(TestIdentifier testIdentifier) {
Instant startInstant = getStartInstant(testIdentifier);
Instant endInstant = getEndInstant(testIdentifier);
return TimeUnit.MILLISECONDS.toSeconds(Duration.between(startInstant, endInstant).toMillis());
}
Instant getStartInstant(TestIdentifier testIdentifier) {
return this.startInstants.getOrDefault(testIdentifier, Instant.EPOCH);
}
Instant getEndInstant(TestIdentifier testIdentifier) {
return this.endInstants.getOrDefault(testIdentifier, getStartInstant(testIdentifier));
}
String getSkipReason(TestIdentifier testIdentifier) {
return findSkippedAncestor(testIdentifier)
.map(skippedTestIdentifier -> {
String reason = this.skippedTests.get(skippedTestIdentifier);
if (!testIdentifier.equals(skippedTestIdentifier)) {
reason = "parent was skipped: '" + reason + "'";
}
return reason;
})
.orElse(null);
}
List getResults(TestIdentifier testIdentifier) {
return getAncestors(testIdentifier).stream()
.map(this.finishedTests::get)
.filter(Objects::nonNull)
.collect(toList());
}
List getReportEntries(TestIdentifier testIdentifier) {
return this.reportEntries.getOrDefault(testIdentifier, emptyList());
}
private Optional findSkippedAncestor(TestIdentifier testIdentifier) {
return findAncestor(testIdentifier, this.skippedTests::containsKey);
}
private Optional findAncestor(TestIdentifier testIdentifier, Predicate predicate) {
Optional current = Optional.of(testIdentifier);
while (current.isPresent()) {
if (predicate.test(current.get())) {
return current;
}
current = this.testPlan.getParent(current.get());
}
return Optional.empty();
}
private List getAncestors(TestIdentifier testIdentifier) {
TestIdentifier current = testIdentifier;
List ancestors = new ArrayList<>();
while (current != null) {
ancestors.add(current);
current = this.testPlan.getParent(current).orElse(null);
}
return ancestors;
}
}