diff --git a/pom.xml b/pom.xml index ef6867c..249f8f3 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ me.fabriciorby maven-surefire-junit5-tree-reporter - 1.0.1 + 1.1.0 jar maven-surefire-junit5-tree-reporter diff --git a/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoTreeReporter.java b/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoTreeReporter.java index 46732e9..15730a2 100644 --- a/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoTreeReporter.java +++ b/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoTreeReporter.java @@ -20,7 +20,7 @@ */ import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; -import org.apache.maven.plugin.surefire.report.ConsoleTreeReporter; +import org.apache.maven.plugin.surefire.report.ConsoleTreeReporterAscii; import org.apache.maven.plugin.surefire.report.TestSetStats; import org.apache.maven.plugin.surefire.report.WrappedReportEntry; import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener; @@ -35,7 +35,7 @@ public class JUnit5StatelessTestsetInfoTreeReporter extends JUnit5StatelessTests @Override public StatelessTestsetInfoConsoleReportEventListener createListener( ConsoleLogger logger) { - return new ConsoleTreeReporter(logger, isUsePhrasedClassNameInRunning(), + return new ConsoleTreeReporterAscii(logger, isUsePhrasedClassNameInRunning(), isUsePhrasedClassNameInTestCaseSummary()); } diff --git a/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporter.java b/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterAscii.java similarity index 67% rename from src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporter.java rename to src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterAscii.java index 7ae91b0..a15825d 100644 --- a/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporter.java +++ b/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterAscii.java @@ -20,8 +20,8 @@ */ import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; -import org.apache.maven.surefire.api.report.TestSetReportEntry; +import java.util.Collection; import java.util.List; /** @@ -29,21 +29,16 @@ * * @author Fabrício Yamamoto */ -public class ConsoleTreeReporter extends ConsoleReporter { +public class ConsoleTreeReporterAscii extends ConsoleTreeReporterBase { - public ConsoleTreeReporter(ConsoleLogger logger, boolean usePhrasedClassNameInRunning, - boolean usePhrasedClassNameInTestCaseSummary) { + public ConsoleTreeReporterAscii(ConsoleLogger logger, boolean usePhrasedClassNameInRunning, + boolean usePhrasedClassNameInTestCaseSummary) { super(logger, usePhrasedClassNameInRunning, usePhrasedClassNameInTestCaseSummary); } @Override - public void testSetStarting(TestSetReportEntry report) { - } - - @Override - public void testSetCompleted(WrappedReportEntry report, TestSetStats testSetStats, List testResults) { - new TreePrinter(getConsoleLogger(), report, testSetStats) - .printTests(); + TreePrinter getTreePrinter(List classEntries, List testEntries) { + return new TreePrinter(getConsoleLogger(), classEntries, testEntries); } } diff --git a/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterBase.java b/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterBase.java new file mode 100644 index 0000000..1238714 --- /dev/null +++ b/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterBase.java @@ -0,0 +1,29 @@ +package org.apache.maven.plugin.surefire.report; + +import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.surefire.api.report.TestSetReportEntry; + +import java.util.List; + +abstract class ConsoleTreeReporterBase extends ConsoleReporter { + + public ConsoleTreeReporterBase(ConsoleLogger logger, boolean usePhrasedClassNameInRunning, + boolean usePhrasedClassNameInTestCaseSummary) { + super(logger, usePhrasedClassNameInRunning, usePhrasedClassNameInTestCaseSummary); + } + + abstract TreePrinter getTreePrinter(List classEntries, List testEntries); + + @Override + public void testSetStarting(TestSetReportEntry report) { + new TestReportHandler(report) + .prepare(); + } + + @Override + public void testSetCompleted(WrappedReportEntry report, TestSetStats testSetStats, List testResults) { + new TestReportHandler(report, testSetStats) + .print(this::getTreePrinter); + } + +} diff --git a/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterUnicode.java b/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterUnicode.java index e76d236..e92e1ff 100644 --- a/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterUnicode.java +++ b/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterUnicode.java @@ -21,6 +21,7 @@ import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; +import java.util.Collection; import java.util.List; /** @@ -28,7 +29,7 @@ * * @author Fabrício Yamamoto */ -public class ConsoleTreeReporterUnicode extends ConsoleTreeReporter { +public class ConsoleTreeReporterUnicode extends ConsoleTreeReporterBase { public ConsoleTreeReporterUnicode(ConsoleLogger logger, boolean usePhrasedClassNameInRunning, boolean usePhrasedClassNameInTestCaseSummary) { @@ -36,9 +37,8 @@ public ConsoleTreeReporterUnicode(ConsoleLogger logger, boolean usePhrasedClassN } @Override - public void testSetCompleted(WrappedReportEntry report, TestSetStats testSetStats, List testResults) { - new TreePrinter(getConsoleLogger(), report, testSetStats, Theme.UNICODE) - .printTests(); + TreePrinter getTreePrinter(List classEntries, List testEntries) { + return new TreePrinter(getConsoleLogger(), classEntries, testEntries, Theme.UNICODE); } } diff --git a/src/main/java/org/apache/maven/plugin/surefire/report/TestReportHandler.java b/src/main/java/org/apache/maven/plugin/surefire/report/TestReportHandler.java new file mode 100644 index 0000000..c804c64 --- /dev/null +++ b/src/main/java/org/apache/maven/plugin/surefire/report/TestReportHandler.java @@ -0,0 +1,145 @@ +package org.apache.maven.plugin.surefire.report; + +import org.apache.maven.surefire.api.report.ReportEntry; + +import java.util.*; +import java.util.function.BiFunction; + +import static java.util.Collections.*; + +public class TestReportHandler { + + protected static final Map> classNames = synchronizedMap(new HashMap<>()); + protected static final Map> classEntries = synchronizedMap(new HashMap<>()); + protected static final Map> testEntries = synchronizedMap(new HashMap<>()); + protected static final int $ = 36; + + private final ReportEntry report; + private final TestSetStats testSetStats; + private final String sourceRootName; + + public TestReportHandler(ReportEntry report, TestSetStats testSetStats) { + this.report = report; + this.testSetStats = testSetStats; + this.sourceRootName = getSourceRootName(); + } + + public TestReportHandler(ReportEntry report) { + this(report, null); + } + + public void prepare() { + if (hasNestedTests()) { + markClassNamesForNestedTests(); + } + } + + public void print(BiFunction,List, TreePrinter> getTreePrinter) { + if (isMarkedAsNestedTest()) { + prepareEntriesForNestedTests(); + if (isNestedTestReadyToPrint()) { + printNestedTests(getTreePrinter); + } + } else { + printTests(getTreePrinter); + } + } + + private boolean isMarkedAsNestedTest() { + return classNames.containsKey(sourceRootName); + } + + private void prepareClassEntriesForNestedTest() { + classEntries.putIfAbsent(sourceRootName, new ArrayList<>()); + classEntries.computeIfPresent(sourceRootName, addToCollection((WrappedReportEntry) report)); + } + + private List getClassEntryList() { + return classEntries.get(sourceRootName); + } + + private void markClassNamesForNestedTests() { + classNames.putIfAbsent(sourceRootName, new HashSet<>(singleton(sourceRootName))); + classNames.computeIfPresent(sourceRootName, addToCollection(report.getSourceName())); + } + + private Set getClassNameList() { + return classNames.get(sourceRootName); + } + + private void prepareTestEntriesForNestedTest() { + testEntries.putIfAbsent(sourceRootName, new ArrayList<>(testSetStats.getReportEntries())); + } + + private List getTestEntryList() { + return testEntries.get(sourceRootName); + } + + private void cleanEntries() { + classNames.remove(sourceRootName); + classEntries.remove(sourceRootName); + testEntries.remove(sourceRootName); + } + + private void sortClassEntryList() { + getClassEntryList() + .sort(Comparator.comparing(ReportEntry::getSourceName)); + } + + private void prepareEntriesForNestedTests() { + if (hasNestedTests()) { + prepareTestEntriesForNestedTest(); + } + prepareClassEntriesForNestedTest(); + } + + private boolean isNestedTestReadyToPrint() { + return getClassEntryList().size() == getClassNameList().size(); + } + + private void printNestedTests(BiFunction,List, TreePrinter> getTreePrinter) { + sortClassEntryList(); + getTreePrinter + .apply(getClassEntryList(), getTestEntryList()) + .printTests(); + cleanEntries(); + } + + private void printTests(BiFunction,List, TreePrinter> getTreePrinter) { + getTreePrinter + .apply(singletonList((WrappedReportEntry) report), new ArrayList<>(testSetStats.getReportEntries())) + .printTests(); + } + + private > BiFunction addToCollection(K obj) { + return (k, v) -> { + v.add(obj); + return v; + }; + } + + private String getSourceRootName() { + return report.getSourceName().split("\\$", -1)[0]; + } + + private boolean hasNestedTests() { + if (this.testSetStats == null) { + return hasNestedTests(report); + } else { + return hasNestedTests(testSetStats); + } + } + + private boolean hasNestedTests(TestSetStats testSetStats) { + return testSetStats.getReportEntries() + .stream() + .anyMatch(this::hasNestedTests); + } + + private boolean hasNestedTests(ReportEntry reportEntry) { + return reportEntry.getSourceName() + .chars() + .filter(c -> c == $) + .count() > 0; + } +} diff --git a/src/main/java/org/apache/maven/plugin/surefire/report/TreePrinter.java b/src/main/java/org/apache/maven/plugin/surefire/report/TreePrinter.java index 8800447..5a92160 100644 --- a/src/main/java/org/apache/maven/plugin/surefire/report/TreePrinter.java +++ b/src/main/java/org/apache/maven/plugin/surefire/report/TreePrinter.java @@ -41,42 +41,42 @@ public class TreePrinter { private final ConsoleLogger consoleLogger; - private final WrappedReportEntry classResult; + private final List classResults; + private final List testSetStats; private final List sourceNames; private final Set distinctSourceName; - private final TestSetStats testSetStats; private final Theme theme; private static final int $ = 36; - public TreePrinter(ConsoleLogger consoleLogger, WrappedReportEntry classResult, TestSetStats testSetStats, Theme theme) { + public TreePrinter(ConsoleLogger consoleLogger, List classResults, List testSetStats, Theme theme) { this.consoleLogger = consoleLogger; - this.classResult = classResult; - this.sourceNames = getSourceNames(testSetStats); - this.distinctSourceName = getDistinctSourceNames(testSetStats); + this.classResults = classResults; this.testSetStats = testSetStats; + this.sourceNames = getSourceNames(); + this.distinctSourceName = getDistinctSourceNames(); this.theme = theme; } - public TreePrinter(ConsoleLogger consoleLogger, WrappedReportEntry classResult, TestSetStats testSetStats) { - this(consoleLogger, classResult, testSetStats, Theme.ASCII); + public TreePrinter(ConsoleLogger consoleLogger, List classResults, List testSetStats) { + this(consoleLogger, classResults, testSetStats, Theme.ASCII); } - private List getSourceNames(TestSetStats testSetStats) { - return testSetStats.getReportEntries() + private List getSourceNames() { + return testSetStats .stream() .map(WrappedReportEntry::getSourceName) .collect(toList()); } - private Set getDistinctSourceNames(TestSetStats testSetStats) { - return testSetStats.getReportEntries() + private Set getDistinctSourceNames() { + return testSetStats .stream() .map(WrappedReportEntry::getSourceName) .collect(toSet()); } public void printTests() { - testSetStats.getReportEntries() + testSetStats .stream() .map(TestPrinter::new) .forEach(TestPrinter::printTest); @@ -85,7 +85,7 @@ public void printTests() { private class TestPrinter { private final WrappedReportEntry testResult; - private final long treeLength; + private final int treeLength; public TestPrinter(WrappedReportEntry testResult) { this.testResult = testResult; @@ -157,10 +157,10 @@ private void printClass() { } else { builder.a(theme.entry()); } + concatenateWithTestGroup(builder, testResult, !isBlank(testResult.getReportNameWithGroup())); - if (treeLength == 0L) { - builder.a(" - " + classResult.elapsedTimeAsString() + "s"); - } + builder.a(" - " + classResults.get(treeLength).elapsedTimeAsString() + "s"); + println(builder.toString()); } @@ -184,8 +184,8 @@ private MessageBuilder getTestPrefix() { return builder; } - private long getTreeLength() { - return testResult.getSourceName() + private int getTreeLength() { + return (int) testResult.getSourceName() .chars() .filter(c -> c == $) .count(); diff --git a/src/test/java/NestedExampleTest.java b/src/test/java/NestedExampleTest.java index 77fbd04..c175662 100644 --- a/src/test/java/NestedExampleTest.java +++ b/src/test/java/NestedExampleTest.java @@ -7,7 +7,8 @@ public class NestedExampleTest { @Test @DisplayName("Should pass") - void test() { + void test() throws InterruptedException { + Thread.sleep(100); } @Nested @@ -16,7 +17,8 @@ class InnerTest { @Test @DisplayName("Inner test should pass") - void test() { + void test() throws InterruptedException { + Thread.sleep(200); } @Nested @@ -25,7 +27,8 @@ class InnerInnerTest { @Test @DisplayName("Inner Inner Test should pass") - void test() { + void test() throws InterruptedException { + Thread.sleep(300); } @Nested @@ -34,7 +37,8 @@ class InnerInnerInnerTest { @Test @DisplayName("Inner Inner Inner Test should pass") - void test() { + void test() throws InterruptedException { + Thread.sleep(400); } } @@ -45,7 +49,8 @@ void test() { @Test @DisplayName("Should pass2") - void test2() { + void test2() throws InterruptedException { + Thread.sleep(500); } } diff --git a/src/test/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterTest.java b/src/test/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterTest.java index 2920e22..37b120d 100644 --- a/src/test/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterTest.java +++ b/src/test/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterTest.java @@ -5,6 +5,8 @@ import org.apache.maven.surefire.api.report.SimpleReportEntry; import org.codehaus.plexus.DefaultPlexusContainer; import org.codehaus.plexus.PlexusContainerException; +import org.codehaus.plexus.logging.Logger; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; @@ -13,10 +15,18 @@ class ConsoleTreeReporterTest { //Test for NestedExampleTest - Utf8RecodingDeferredFileOutputStream stdout = new Utf8RecodingDeferredFileOutputStream("stdout"); Utf8RecodingDeferredFileOutputStream stderr = new Utf8RecodingDeferredFileOutputStream("stderr"); + static DefaultPlexusContainer container; + static Logger logger; + + @BeforeAll + static void setupContainer() throws PlexusContainerException { + container = new DefaultPlexusContainer(); + logger = container.getLogger(); + } + @Test void testSetStarting() { //Runs 4 times for this class @@ -24,10 +34,16 @@ void testSetStarting() { SimpleReportEntry simpleReportEntry2 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$InnerTest", "Inner Test", null, null); SimpleReportEntry simpleReportEntry3 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$InnerTest$InnerInnerTest", "Inner Inner Test", null, null); SimpleReportEntry simpleReportEntry4 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest$InnerTest$InnerInnerTest$InnerInnerInnerTest", "Inner Inner Inner Test", null, null); + + ConsoleTreeReporterAscii consoleTreeReporter = new ConsoleTreeReporterAscii(new PluginConsoleLogger(logger), false, false); + consoleTreeReporter.testSetStarting(simpleReportEntry1); + consoleTreeReporter.testSetStarting(simpleReportEntry2); + consoleTreeReporter.testSetStarting(simpleReportEntry3); + consoleTreeReporter.testSetStarting(simpleReportEntry4); } @Test - void testSetCompleted() throws PlexusContainerException { + void testSetCompleted() { //TestStarting parameters SimpleReportEntry simpleReportEntry1 = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "NestedExampleTest", "Nested Sample", null, null); @@ -56,19 +72,18 @@ void testSetCompleted() throws PlexusContainerException { testSetStats.testSucceeded(wrappedReportEntry4); testSetStats.testSucceeded(wrappedReportEntry5); - SimpleReportEntry classEntry = new SimpleReportEntry(RunMode.NORMAL_RUN, 123L, "source", "sourceTest", "name", "nameTest"); - WrappedReportEntry classReportEntry = new WrappedReportEntry(classEntry, ReportEntryType.SUCCESS, 112, stdout, stderr); + TestSetStats testSetStatsForClass = new TestSetStats(false, true); - DefaultPlexusContainer container = new DefaultPlexusContainer(); - container.getLogger(); - - ConsoleTreeReporter consoleTreeReporter = new ConsoleTreeReporter(new PluginConsoleLogger(container.getLogger()), false, false); - consoleTreeReporter.testSetStarting(classReportEntry); + ConsoleTreeReporterAscii consoleTreeReporter = new ConsoleTreeReporterAscii(new PluginConsoleLogger(logger), false, false); consoleTreeReporter.testSetStarting(simpleReportEntry1); consoleTreeReporter.testSetStarting(simpleReportEntry2); consoleTreeReporter.testSetStarting(simpleReportEntry3); consoleTreeReporter.testSetStarting(simpleReportEntry4); - consoleTreeReporter.testSetCompleted(classReportEntry, testSetStats, null); + consoleTreeReporter.testSetCompleted(wrappedReportEntry5, testSetStats, null); + consoleTreeReporter.testSetCompleted(wrappedReportEntry4, testSetStatsForClass, null); + consoleTreeReporter.testSetCompleted(wrappedReportEntry3, testSetStatsForClass, null); + consoleTreeReporter.testSetCompleted(wrappedReportEntry2, testSetStatsForClass, null); + //TODO see how to unit test this }