Summary.java
package io.github.giulong.spectrum.utils;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import io.github.giulong.spectrum.enums.Result;
import io.github.giulong.spectrum.interfaces.SessionHook;
import io.github.giulong.spectrum.interfaces.reports.CanReportSummary;
import io.github.giulong.spectrum.interfaces.reports.Reportable;
import io.github.giulong.spectrum.utils.reporters.FileReporter;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
import org.junit.platform.launcher.listeners.TestExecutionSummary;
import org.mvel2.MVEL;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static io.github.giulong.spectrum.enums.Result.FAILED;
import static io.github.giulong.spectrum.enums.Result.SUCCESSFUL;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
@Getter
@Slf4j
public class Summary implements SessionHook, Reportable {
@JsonIgnore
private final FreeMarkerWrapper freeMarkerWrapper = FreeMarkerWrapper.getInstance();
@JsonIgnore
private final FileUtils fileUtils = FileUtils.getInstance();
@JsonIgnore
private final SummaryGeneratingListener summaryGeneratingListener = new SummaryGeneratingListener();
@JsonPropertyDescription("List of reporters that will produce the summary in specific formats")
@SuppressWarnings("unused")
private List<CanReportSummary> reporters;
@JsonPropertyDescription("Condition to be evaluated. If true, the execution is successful")
@SuppressWarnings("unused")
private String condition;
@JsonIgnore
private final Map<String, Object> vars = new HashMap<>();
@Override
public void sessionOpened() {
reporters
.stream()
.filter(canReportSummary -> canReportSummary instanceof FileReporter)
.map(FileReporter.class::cast)
.map(FileReporter::getOutput)
.forEach(output -> {
final String reportPath = Path.of(output).toAbsolutePath().toString().replace("\\", "/");
log.info("After the execution, you'll find the {} summary at file:///{}", fileUtils.getExtensionOf(output), reportPath);
});
}
@Override
public void sessionClosed() {
log.debug("Session closed hook");
final TestExecutionSummary summary = summaryGeneratingListener.getSummary();
final long total = summary.getTestsFoundCount();
final long succeeded = summary.getTestsSucceededCount();
final long failed = summary.getTestsFailedCount();
final long aborted = summary.getTestsAbortedCount();
final long disabled = summary.getTestsSkippedCount();
final long duration = summary.getTimeFinished() - summary.getTimeStarted();
final long hours = MILLISECONDS.toHours(duration);
final long minutes = MILLISECONDS.toMinutes(duration) % 60;
final long seconds = MILLISECONDS.toSeconds(duration) % 60;
vars.putAll(Vars.getInstance());
vars.put("summary", summary);
vars.put("duration", String.format("%02d:%02d:%02d", hours, minutes, seconds));
vars.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")));
vars.put("total", total);
vars.put("successfulPercentage", (double) succeeded / total * 100);
vars.put("failedPercentage", (double) failed / total * 100);
vars.put("abortedPercentage", (double) aborted / total * 100);
vars.put("disabledPercentage", (double) disabled / total * 100);
vars.put("condition", condition);
vars.put("interpolatedCondition", interpolateCondition());
vars.put("executionSuccessful", isExecutionSuccessful());
reporters.forEach(reporter -> reporter.flush(this));
}
@JsonIgnore
public boolean isExecutionSuccessful() {
final boolean executionSuccessful = Boolean.parseBoolean(String.valueOf(MVEL.eval(interpolateCondition(), vars)));
log.info("Execution successful? {}", executionSuccessful);
return executionSuccessful;
}
public Result toResult() {
return isExecutionSuccessful() ? SUCCESSFUL : FAILED;
}
String interpolateCondition() {
return freeMarkerWrapper.interpolate(condition, vars);
}
}