From 411fb39d9187727bfc3ddabb1b032343893a8084 Mon Sep 17 00:00:00 2001 From: ReaJason Date: Tue, 3 Dec 2024 21:19:21 +0800 Subject: [PATCH] test: enhance integration report --- .github/workflows/ci.yaml | 2 +- .../MarkdownTestExecutionListener.java | 99 ++++++++++++++----- 2 files changed, 77 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e08e6aed..6bd15397 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,7 +24,7 @@ jobs: run: ./gradlew :integration-test:test --info continue-on-error: true - name: Export Integration Test Summary - run: cat integration-test/build/test-results/result.md >> $GITHUB_STEP_SUMMARY + run: cat integration-test/build/test-results/report.md >> $GITHUB_STEP_SUMMARY - name: Merge Jacoco run: ./gradlew jacocoTestReport - name: Generate JaCoCo Badge diff --git a/integration-test/src/test/java/com/reajason/javaweb/MarkdownTestExecutionListener.java b/integration-test/src/test/java/com/reajason/javaweb/MarkdownTestExecutionListener.java index a145efea..f23ae38c 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/MarkdownTestExecutionListener.java +++ b/integration-test/src/test/java/com/reajason/javaweb/MarkdownTestExecutionListener.java @@ -1,5 +1,7 @@ package com.reajason.javaweb; +import lombok.Builder; +import lombok.Data; import lombok.SneakyThrows; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; @@ -14,21 +16,33 @@ import java.nio.file.StandardOpenOption; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; /** * @author ReaJason * @since 2024/12/1 */ public class MarkdownTestExecutionListener implements TestExecutionListener { + @Data + @Builder + static class TestCase { + private String imageName; + private String shellType; + private String packer; + private Duration duration; + private TestExecutionResult.Status status; + } - private final Map timeStamps = new HashMap<>(); + private final Map timeStamps = new ConcurrentHashMap<>(); + private final Map> testCases = new ConcurrentHashMap<>(); private Instant startTime; - private final Path markdownPath = Paths.get("build", "test-results", "result.md"); - private final List passedResults = new ArrayList<>(); - private final List failedResults = new ArrayList<>(); + private final Path markdownPath = Paths.get("build", "test-results", "report.md"); + private final AtomicLong totalCount = new AtomicLong(0); + private final AtomicLong successCount = new AtomicLong(0); @SneakyThrows @Override @@ -37,7 +51,7 @@ public class MarkdownTestExecutionListener implements TestExecutionListener { ArrayList lines = new ArrayList<>(); lines.add("## Integration Test"); startTime = Instant.now(); - lines.add("- Started At: " + startTime); + lines.add("- Started: " + startTime); Files.write(markdownPath, lines, StandardOpenOption.CREATE_NEW); } @@ -46,29 +60,67 @@ public class MarkdownTestExecutionListener implements TestExecutionListener { public void testPlanExecutionFinished(TestPlan testPlan) { List lines = new ArrayList<>(); Instant endTime = Instant.now(); - lines.add("- Finished At: " + endTime); - lines.add("- Total Duration: " + Duration.between(startTime, endTime).getSeconds() + " seconds"); + lines.add("- Finished: " + endTime); + Duration duration = Duration.between(startTime, endTime); + lines.add("- Total Duration: " + getDuration(duration)); + lines.add(String.format("- Total Cases: %d/%d, %d failed", successCount.get(), totalCount.get(), totalCount.get() - successCount.get())); lines.add(""); - lines.add("| **Image Name** | **Shell Type** | **Packer** | **Status**| **Duration(ms)** |"); - lines.add("|----------------|----------------|------------|-----------|------------------|"); - lines.addAll(failedResults); - lines.addAll(passedResults); + + for (Map.Entry> entry : testCases.entrySet()) { + lines.add(String.format("### %s", entry.getKey())); + lines.add("|**Shell Type** | **Packer** | **Status**| **Duration(ms)** |"); + lines.add("|---------------|------------|-----------|------------------|"); + List value = entry.getValue().stream().sorted((tc1, tc2) -> { + if (tc1.getStatus() == tc2.getStatus()) { + return 0; + } + return tc1.getStatus() == TestExecutionResult.Status.FAILED ? -1 : 1; + }).collect(Collectors.toList()); + for (TestCase testCase : value) { + String status = testCase.getStatus().equals(TestExecutionResult.Status.SUCCESSFUL) ? "✔" : "✘"; + lines.add("|" + testCase.getShellType() + "|" + testCase.getPacker() + "|" + status + "|" + testCase.getDuration().toMillis() + "|"); + } + } + Files.write(markdownPath, lines, StandardOpenOption.APPEND); } + private String getDuration(Duration duration) { + long totalSeconds = duration.getSeconds(); + long minutes = totalSeconds / 60; + long seconds = totalSeconds % 60; + if (totalSeconds < 60) { + return String.format("%d seconds", totalSeconds); + } else { + return String.format("%d minutes and %d seconds", minutes, seconds); + } + } + @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { - if (testIdentifier.isTest()) { - Instant startTime = timeStamps.get(testIdentifier.getUniqueIdObject()); - if (startTime != null) { - String[] split = testIdentifier.getDisplayName().split("\\|"); - if (split.length == 3) { - if (testExecutionResult.getStatus().equals(TestExecutionResult.Status.SUCCESSFUL)) { - passedResults.add("|" + split[0].trim() + "|" + split[1].trim() + "|" + split[2].trim() + "|✔|" + Duration.between(startTime, Instant.now()).toMillis() + "|"); - } else { - failedResults.add("|" + split[0].trim() + "|" + split[1].trim() + "|" + split[2].trim() + "|✘|" + Duration.between(startTime, Instant.now()).toMillis() + "|"); - } - } + if (!testIdentifier.isTest()) { + return; + } + Instant startTime = timeStamps.get(testIdentifier.getUniqueIdObject()); + if (startTime == null) { + return; + } + String[] split = testIdentifier.getDisplayName().split("\\|"); + if (split.length == 3) { + String imageName = split[0].trim(); + String shellType = split[1].trim(); + String packer = split[2].trim(); + List cases = testCases.getOrDefault(imageName, new ArrayList<>()); + cases.add(TestCase.builder() + .imageName(imageName) + .shellType(shellType) + .packer(packer) + .duration(Duration.between(startTime, Instant.now())) + .status(testExecutionResult.getStatus()) + .build()); + testCases.put(imageName, cases); + if (testExecutionResult.getStatus().equals(TestExecutionResult.Status.SUCCESSFUL)) { + successCount.incrementAndGet(); } } } @@ -76,6 +128,7 @@ public class MarkdownTestExecutionListener implements TestExecutionListener { @Override public void executionStarted(TestIdentifier testIdentifier) { if (testIdentifier.isTest()) { + totalCount.incrementAndGet(); timeStamps.put(testIdentifier.getUniqueIdObject(), Instant.now()); } }