From 18dd746e4f77808d471f97cb545293d3a81ff174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabr=C3=ADcio=20Yamamoto?= Date: Sat, 13 May 2023 23:27:20 +0200 Subject: [PATCH] Add features from #39 and update pom.xml versions (#42) * Fixed #30 - Upgrade to maven-surefire-plugin:3.0.0-M8 (#31) * Fixed #32 - Using JUnit Jupiter BOM 5.9.2 (#33) * Fixed #34 - Using mockito-bom 4.11.0 (#35) * Add options to print stack trace / stdout / stderr on error or failure (#39) * Update README, pom.xml and make it Java 8 compatible (#41) --------- Co-authored-by: Karl Heinz Marbaise Co-authored-by: Andre Wachsmuth Co-authored-by: Andre Wachsmuth --- .gitignore | 23 ++- README.md | 79 +++++---- pom.xml | 37 +++- ...Unit5StatelessTestsetInfoReporterBase.java | 32 ---- ...Unit5StatelessTestsetInfoTreeReporter.java | 165 +++++++++++++++--- ...atelessTestsetInfoTreeReporterUnicode.java | 37 +--- .../loader/SurefireClassLoaderModifier.java | 6 +- .../surefire/report/ConsoleTreeReporter.java | 29 +++ .../report/ConsoleTreeReporterAscii.java | 44 ----- .../report/ConsoleTreeReporterBase.java | 29 --- .../report/ConsoleTreeReporterUnicode.java | 44 ----- .../surefire/report/ReporterOptions.java | 153 ++++++++++++++++ .../maven/plugin/surefire/report/Theme.java | 25 ++- .../plugin/surefire/report/TreePrinter.java | 108 ++++++++++-- src/test/java/DynamicExampleTest.java | 28 +++ .../report/ConsoleTreeReporterTest.java | 4 +- 16 files changed, 564 insertions(+), 279 deletions(-) delete mode 100644 src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoReporterBase.java create mode 100644 src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporter.java delete mode 100644 src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterAscii.java delete mode 100644 src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterBase.java delete mode 100644 src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterUnicode.java create mode 100644 src/main/java/org/apache/maven/plugin/surefire/report/ReporterOptions.java create mode 100644 src/test/java/DynamicExampleTest.java diff --git a/.gitignore b/.gitignore index 3c906eb..76a910d 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,25 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* -settings.xml \ No newline at end of file +settings.xml + +### Eclipse ### +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders +.project +.classpath + +# Locally stored "Eclipse launch configurations" +*.launch + +# Java annotation processor (APT) +.factorypath diff --git a/README.md b/README.md index 6fb9577..f488374 100644 --- a/README.md +++ b/README.md @@ -7,35 +7,21 @@ This is a dependency for [maven-surefire-plugin](https://maven.apache.org/surefi [![Maven Central](https://img.shields.io/maven-central/v/me.fabriciorby/maven-surefire-junit5-tree-reporter?style=for-the-badge)](https://search.maven.org/artifact/me.fabriciorby/maven-surefire-junit5-tree-reporter) [![Apache License, Version 2.0, January 2004](https://img.shields.io/github/license/apache/maven.svg?label=License&style=for-the-badge)](http://www.apache.org/licenses/LICENSE-2.0) -## Output - -The output can be printed in two ways. - -### UNICODE -![Imgur](https://i.imgur.com/JdrP2QN.png "UNICODE Output") -``org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporterUnicode`` - -### ASCII -![Imgur](https://i.imgur.com/FzcIWwe.png "ASCII Output") -``org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter`` - ## Installation The Maven Repository can be found [here](https://mvnrepository.com/artifact/me.fabriciorby/maven-surefire-junit5-tree-reporter). Configure your POM like the following -### UNICODE Output - ```xml maven-surefire-plugin - 3.0.0-M7 + 3.1.0 me.fabriciorby maven-surefire-junit5-tree-reporter - 1.1.0 + 1.2.0 @@ -44,35 +30,52 @@ Configure your POM like the following true + implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter"> ``` -### ASCII Output +## Output Theme + +The output can be printed using two Themes: UNICODE and ASCII (by default). +### UNICODE ```xml - - maven-surefire-plugin - 3.0.0-M7 - - - me.fabriciorby - maven-surefire-junit5-tree-reporter - 1.1.0 - - - - plain - - true - - - - - + + UNICODE + +``` +![Imgur](https://i.imgur.com/JdrP2QN.png "UNICODE Output") + + +### ASCII +```xml + + ASCII + +``` +![Imgur](https://i.imgur.com/FzcIWwe.png "ASCII Output") + + +## Failure details + +By default, `true` disables all console output. To debug test failures, it may be useful to see the console output and stack traces when a test fails. To do so, you can configure this extension like this: + +```xml + + true + true + true + true + false + true + true + false + ``` ## Contribute diff --git a/pom.xml b/pom.xml index 249f8f3..e5c73dc 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ me.fabriciorby maven-surefire-junit5-tree-reporter - 1.1.0 + 1.2.0 jar maven-surefire-junit5-tree-reporter @@ -14,27 +14,44 @@ https://github.com/fabriciorby/maven-surefire-junit5-tree-reporter - 5.9.0-M1 1.8 1.8 - 3.0.0-M7 + 3.1.0 - org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporterUnicode + org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoTreeReporter 3.2.1 3.2.0 - 3.0.0-M1 + 3.1.1 1.6 - 4.6.1 1.6.13 UTF-8 + 4.11.0 + 5.9.3 + + + + org.mockito + mockito-bom + ${mockito-bom.version} + import + pom + + + org.junit + junit-bom + ${junit-bom.version} + import + pom + + + org.junit.jupiter junit-jupiter - ${junit-jupiter.version} test @@ -46,13 +63,11 @@ org.mockito mockito-core - ${mockito.version} test org.mockito mockito-junit-jupiter - ${mockito.version} test @@ -113,6 +128,7 @@ + UNICODE @@ -139,6 +155,9 @@ jar + + ${java.home}/bin/javadoc + diff --git a/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoReporterBase.java b/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoReporterBase.java deleted file mode 100644 index 5ceed10..0000000 --- a/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoReporterBase.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.apache.maven.plugin.surefire.extensions.junit5; - -import org.apache.maven.plugin.surefire.loader.SurefireClassLoaderModifier; - -/** - * Extension of {@link JUnit5StatelessTestsetInfoReporter file and console reporter of test-set} for JUnit5. - * - * @author Fabrício Yamamoto (fabriciorby) - */ -public abstract class JUnit5StatelessTestsetInfoReporterBase extends JUnit5StatelessTestsetInfoReporter { - - @Override - public Object clone(ClassLoader target) { - try { - new SurefireClassLoaderModifier(target).addThisToSurefireClassLoader(); - return super.clone(target); - } catch (ReflectiveOperationException e) { - throw new IllegalStateException(e.getLocalizedMessage()); - } - } - - @Override - public String toString() { - return this.getClass().getSimpleName() + "{" - + "disable=" + isDisable() - + ", usePhrasedFileName=" + isUsePhrasedFileName() - + ", usePhrasedClassNameInRunning=" + isUsePhrasedClassNameInRunning() - + ", usePhrasedClassNameInTestCaseSummary=" + isUsePhrasedClassNameInTestCaseSummary() - + "}"; - } - -} 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 15730a2..ef41c25 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 @@ -1,42 +1,157 @@ package org.apache.maven.plugin.surefire.extensions.junit5; -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - +import org.apache.maven.plugin.surefire.loader.SurefireClassLoaderModifier; import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; -import org.apache.maven.plugin.surefire.report.ConsoleTreeReporterAscii; +import org.apache.maven.plugin.surefire.report.ConsoleTreeReporter; +import org.apache.maven.plugin.surefire.report.ReporterOptions; import org.apache.maven.plugin.surefire.report.TestSetStats; +import org.apache.maven.plugin.surefire.report.Theme; import org.apache.maven.plugin.surefire.report.WrappedReportEntry; import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener; /** - * Extension of {@link JUnit5StatelessTestsetInfoReporter file and console reporter of test-set} for JUnit5. + * Extension of {@link JUnit5StatelessTestsetInfoReporter file and console + * reporter of test-set} for JUnit5. * - * @author Fabrício Yamamoto (fabriciorby) + * @author Fabrício Yamamoto + * (fabriciorby) */ -public class JUnit5StatelessTestsetInfoTreeReporter extends JUnit5StatelessTestsetInfoReporterBase { +public class JUnit5StatelessTestsetInfoTreeReporter extends JUnit5StatelessTestsetInfoReporter { + private boolean printStacktraceOnError; + private boolean printStacktraceOnFailure; + private boolean printStderrOnError; + private boolean printStderrOnFailure; + private boolean printStderrOnSuccess; + private boolean printStdoutOnError; + private boolean printStdoutOnFailure; + private boolean printStdoutOnSuccess; + private Theme theme = Theme.ASCII; + + @Override + public Object clone(ClassLoader target) { + try { + new SurefireClassLoaderModifier(target).addThisToSurefireClassLoader(); + + Object clone = super.clone(target); + + Class cls = clone.getClass(); + cls.getMethod("setPrintStacktraceOnError", boolean.class).invoke(clone, isPrintStacktraceOnError()); + cls.getMethod("setPrintStacktraceOnFailure", boolean.class).invoke(clone, isPrintStacktraceOnFailure()); + cls.getMethod("setPrintStderrOnError", boolean.class).invoke(clone, isPrintStderrOnError()); + cls.getMethod("setPrintStderrOnFailure", boolean.class).invoke(clone, isPrintStderrOnFailure()); + cls.getMethod("setPrintStderrOnSuccess", boolean.class).invoke(clone, isPrintStderrOnSuccess()); + cls.getMethod("setPrintStdoutOnError", boolean.class).invoke(clone, isPrintStdoutOnError()); + cls.getMethod("setPrintStdoutOnFailure", boolean.class).invoke(clone, isPrintStdoutOnFailure()); + cls.getMethod("setPrintStdoutOnSuccess", boolean.class).invoke(clone, isPrintStdoutOnSuccess()); + cls.getMethod("setTheme", Theme.class).invoke(clone, getTheme()); + + return clone; + } catch (ReflectiveOperationException e) { + throw new IllegalStateException(e.getLocalizedMessage()); + } + } @Override public StatelessTestsetInfoConsoleReportEventListener createListener( ConsoleLogger logger) { - return new ConsoleTreeReporterAscii(logger, isUsePhrasedClassNameInRunning(), - isUsePhrasedClassNameInTestCaseSummary()); + return new ConsoleTreeReporter(logger, newReporterOptions()); + } + + public Theme getTheme() { + return theme; } + public boolean isPrintStacktraceOnError() { + return printStacktraceOnError; + } + + public boolean isPrintStacktraceOnFailure() { + return printStacktraceOnFailure; + } + + public boolean isPrintStderrOnError() { + return printStderrOnError; + } + + public boolean isPrintStderrOnFailure() { + return printStderrOnFailure; + } + + public boolean isPrintStderrOnSuccess() { + return printStderrOnSuccess; + } + + public boolean isPrintStdoutOnError() { + return printStdoutOnError; + } + + public boolean isPrintStdoutOnFailure() { + return printStdoutOnFailure; + } + + public boolean isPrintStdoutOnSuccess() { + return printStdoutOnSuccess; + } + + public void setPrintStacktraceOnError(boolean printStacktraceOnError) { + this.printStacktraceOnError = printStacktraceOnError; + } + + public void setPrintStacktraceOnFailure(boolean printStacktraceOnFailure) { + this.printStacktraceOnFailure = printStacktraceOnFailure; + } + + public void setPrintStderrOnError(boolean printStderrOnError) { + this.printStderrOnError = printStderrOnError; + } + + public void setPrintStderrOnFailure(boolean printStderrOnFailure) { + this.printStderrOnFailure = printStderrOnFailure; + } + + public void setPrintStderrOnSuccess(boolean printStderrOnSuccess) { + this.printStderrOnSuccess = printStderrOnSuccess; + } + + public void setPrintStdoutOnError(boolean printStdoutOnError) { + this.printStdoutOnError = printStdoutOnError; + } + + public void setPrintStdoutOnFailure(boolean printStdoutOnFailure) { + this.printStdoutOnFailure = printStdoutOnFailure; + } + + public void setPrintStdoutOnSuccess(boolean printStdoutOnSuccess) { + this.printStdoutOnSuccess = printStdoutOnSuccess; + } + + public void setTheme(Theme theme) { + this.theme = theme; + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + "{" + + "disable=" + isDisable() + + ", usePhrasedFileName=" + isUsePhrasedFileName() + + ", usePhrasedClassNameInRunning=" + isUsePhrasedClassNameInRunning() + + ", usePhrasedClassNameInTestCaseSummary=" + isUsePhrasedClassNameInTestCaseSummary() + + "}"; + } + + private ReporterOptions newReporterOptions() { + return ReporterOptions.builder() + .printStacktraceOnError(isPrintStacktraceOnError()) + .printStacktraceOnFailure(isPrintStacktraceOnFailure()) + .printStderrOnError(isPrintStderrOnError()) + .printStderrOnFailure(isPrintStderrOnFailure()) + .printStderrOnSuccess(isPrintStderrOnSuccess()) + .printStdoutOnError(isPrintStdoutOnError()) + .printStdoutOnFailure(isPrintStdoutOnFailure()) + .printStdoutOnSuccess(isPrintStdoutOnSuccess()) + .usePhrasedClassNameInRunning(isUsePhrasedClassNameInRunning()) + .usePhrasedClassNameInTestCaseSummary(isUsePhrasedClassNameInTestCaseSummary()) + .theme(getTheme()) + .build(); + } } diff --git a/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoTreeReporterUnicode.java b/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoTreeReporterUnicode.java index 45c80a0..880ef40 100644 --- a/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoTreeReporterUnicode.java +++ b/src/main/java/org/apache/maven/plugin/surefire/extensions/junit5/JUnit5StatelessTestsetInfoTreeReporterUnicode.java @@ -1,42 +1,17 @@ package org.apache.maven.plugin.surefire.extensions.junit5; -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; -import org.apache.maven.plugin.surefire.report.ConsoleTreeReporterUnicode; -import org.apache.maven.plugin.surefire.report.TestSetStats; -import org.apache.maven.plugin.surefire.report.WrappedReportEntry; -import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener; +import org.apache.maven.plugin.surefire.report.Theme; /** * Extension of {@link JUnit5StatelessTestsetInfoReporter file and console reporter of test-set} for JUnit5. * + * @deprecated Use {@link JUnit5StatelessTestsetInfoTreeReporter} and set the parameter {@code theme} to {@code UNICODE}. * @author Fabrício Yamamoto (fabriciorby) */ -public class JUnit5StatelessTestsetInfoTreeReporterUnicode extends JUnit5StatelessTestsetInfoReporterBase { - +@Deprecated +public class JUnit5StatelessTestsetInfoTreeReporterUnicode extends JUnit5StatelessTestsetInfoTreeReporter { @Override - public StatelessTestsetInfoConsoleReportEventListener createListener( - ConsoleLogger logger) { - return new ConsoleTreeReporterUnicode(logger, isUsePhrasedClassNameInRunning(), - isUsePhrasedClassNameInTestCaseSummary()); + public Theme getTheme() { + return Theme.UNICODE; } - } diff --git a/src/main/java/org/apache/maven/plugin/surefire/loader/SurefireClassLoaderModifier.java b/src/main/java/org/apache/maven/plugin/surefire/loader/SurefireClassLoaderModifier.java index 185cc28..a85dc33 100644 --- a/src/main/java/org/apache/maven/plugin/surefire/loader/SurefireClassLoaderModifier.java +++ b/src/main/java/org/apache/maven/plugin/surefire/loader/SurefireClassLoaderModifier.java @@ -1,12 +1,12 @@ package org.apache.maven.plugin.surefire.loader; -import org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoReporterBase; - import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.stream.Stream; +import org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoReporter; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -28,7 +28,7 @@ /** * Class created to modify the Surefire ClassLoader during Runtime. - * Needed for {@link JUnit5StatelessTestsetInfoReporterBase#clone()} method, + * Needed for {@link JUnit5StatelessTestsetInfoReporter#clone()} method, * which is used when the unit tests are running using multiple threads. * * @author Fabrício Yamamoto (fabriciorby) diff --git a/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporter.java b/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporter.java new file mode 100644 index 0000000..b640994 --- /dev/null +++ b/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporter.java @@ -0,0 +1,29 @@ +package org.apache.maven.plugin.surefire.report; + +import java.util.List; + +import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.surefire.api.report.TestSetReportEntry; + +public class ConsoleTreeReporter extends ConsoleReporter { + private final ReporterOptions options; + + public ConsoleTreeReporter(ConsoleLogger logger, ReporterOptions options) { + super(logger, options.isUsePhrasedClassNameInRunning(), options.isUsePhrasedClassNameInTestCaseSummary()); + this.options = options; + } + + @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); + } + + private TreePrinter getTreePrinter(List classEntries, List testEntries) { + return new TreePrinter(getConsoleLogger(), classEntries, testEntries, options); + } +} diff --git a/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterAscii.java b/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterAscii.java deleted file mode 100644 index a15825d..0000000 --- a/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterAscii.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.apache.maven.plugin.surefire.report; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; - -import java.util.Collection; -import java.util.List; - -/** - * Tree view class for console reporters. - * - * @author Fabrício Yamamoto - */ -public class ConsoleTreeReporterAscii extends ConsoleTreeReporterBase { - - public ConsoleTreeReporterAscii(ConsoleLogger logger, boolean usePhrasedClassNameInRunning, - boolean usePhrasedClassNameInTestCaseSummary) { - super(logger, usePhrasedClassNameInRunning, usePhrasedClassNameInTestCaseSummary); - } - - @Override - 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 deleted file mode 100644 index 1238714..0000000 --- a/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterBase.java +++ /dev/null @@ -1,29 +0,0 @@ -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 deleted file mode 100644 index e92e1ff..0000000 --- a/src/main/java/org/apache/maven/plugin/surefire/report/ConsoleTreeReporterUnicode.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.apache.maven.plugin.surefire.report; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; - -import java.util.Collection; -import java.util.List; - -/** - * Tree view class for console reporters using UNICODE theme. - * - * @author Fabrício Yamamoto - */ -public class ConsoleTreeReporterUnicode extends ConsoleTreeReporterBase { - - public ConsoleTreeReporterUnicode(ConsoleLogger logger, boolean usePhrasedClassNameInRunning, - boolean usePhrasedClassNameInTestCaseSummary) { - super(logger, usePhrasedClassNameInRunning, usePhrasedClassNameInTestCaseSummary); - } - - @Override - 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/ReporterOptions.java b/src/main/java/org/apache/maven/plugin/surefire/report/ReporterOptions.java new file mode 100644 index 0000000..a8f46ca --- /dev/null +++ b/src/main/java/org/apache/maven/plugin/surefire/report/ReporterOptions.java @@ -0,0 +1,153 @@ +package org.apache.maven.plugin.surefire.report; + +public class ReporterOptions { + private final boolean printStacktraceOnError; + private final boolean printStacktraceOnFailure; + private final boolean printStderrOnError; + private final boolean printStderrOnFailure; + private final boolean printStderrOnSuccess; + private final boolean printStdoutOnError; + private final boolean printStdoutOnFailure; + private final boolean printStdoutOnSuccess; + private final Theme theme; + private final boolean usePhrasedClassNameInRunning; + private final boolean usePhrasedClassNameInTestCaseSummary; + + private ReporterOptions(Builder builder) { + this.printStacktraceOnError = builder.printStacktraceOnError; + this.printStacktraceOnFailure = builder.printStacktraceOnFailure; + this.printStderrOnError = builder.printStderrOnError; + this.printStderrOnFailure = builder.printStderrOnFailure; + this.printStderrOnSuccess = builder.printStderrOnSuccess; + this.printStdoutOnError = builder.printStdoutOnError; + this.printStdoutOnFailure = builder.printStdoutOnFailure; + this.printStdoutOnSuccess = builder.printStdoutOnSuccess; + this.usePhrasedClassNameInRunning = builder.usePhrasedClassNameInRunning; + this.usePhrasedClassNameInTestCaseSummary = builder.usePhrasedClassNameInTestCaseSummary; + this.theme = builder.theme != null ? builder.theme : Theme.ASCII; + } + + public Theme getTheme() { + return theme; + } + + public boolean isPrintStacktraceOnError() { + return printStacktraceOnError; + } + + public boolean isPrintStacktraceOnFailure() { + return printStacktraceOnFailure; + } + + public boolean isPrintStderrOnError() { + return printStderrOnError; + } + + public boolean isPrintStderrOnFailure() { + return printStderrOnFailure; + } + + public boolean isPrintStderrOnSuccess() { + return printStderrOnSuccess; + } + + public boolean isPrintStdoutOnError() { + return printStdoutOnError; + } + + public boolean isPrintStdoutOnFailure() { + return printStdoutOnFailure; + } + + public boolean isPrintStdoutOnSuccess() { + return printStdoutOnSuccess; + } + + public boolean isUsePhrasedClassNameInRunning() { + return usePhrasedClassNameInRunning; + } + + public boolean isUsePhrasedClassNameInTestCaseSummary() { + return usePhrasedClassNameInTestCaseSummary; + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + private boolean printStacktraceOnError; + private boolean printStacktraceOnFailure; + private boolean printStderrOnError; + private boolean printStderrOnFailure; + private boolean printStderrOnSuccess; + private boolean printStdoutOnError; + private boolean printStdoutOnFailure; + private boolean printStdoutOnSuccess; + private Theme theme; + private boolean usePhrasedClassNameInRunning; + private boolean usePhrasedClassNameInTestCaseSummary; + + private Builder() { + } + + public ReporterOptions build() { + return new ReporterOptions(this); + } + + public Builder printStacktraceOnError(boolean printStacktraceOnError) { + this.printStacktraceOnError = printStacktraceOnError; + return this; + } + + public Builder printStacktraceOnFailure(boolean printStacktraceOnFailure) { + this.printStacktraceOnFailure = printStacktraceOnFailure; + return this; + } + + public Builder printStderrOnError(boolean printStderrOnError) { + this.printStderrOnError = printStderrOnError; + return this; + } + + public Builder printStderrOnFailure(boolean printStderrOnFailure) { + this.printStderrOnFailure = printStderrOnFailure; + return this; + } + + public Builder printStderrOnSuccess(boolean printStderrOnSuccess) { + this.printStderrOnSuccess = printStderrOnSuccess; + return this; + } + + public Builder printStdoutOnError(boolean printStdoutOnError) { + this.printStdoutOnError = printStdoutOnError; + return this; + } + + public Builder printStdoutOnFailure(boolean printStdoutOnFailure) { + this.printStdoutOnFailure = printStdoutOnFailure; + return this; + } + + public Builder printStdoutOnSuccess(boolean printStdoutOnSuccess) { + this.printStdoutOnSuccess = printStdoutOnSuccess; + return this; + } + + public Builder theme(Theme theme) { + this.theme = theme; + return this; + } + + public Builder usePhrasedClassNameInRunning(boolean usePhrasedClassNameInRunning) { + this.usePhrasedClassNameInRunning = usePhrasedClassNameInRunning; + return this; + } + + public Builder usePhrasedClassNameInTestCaseSummary(boolean usePhrasedClassNameInTestCaseSummary) { + this.usePhrasedClassNameInTestCaseSummary = usePhrasedClassNameInTestCaseSummary; + return this; + } + } +} diff --git a/src/main/java/org/apache/maven/plugin/surefire/report/Theme.java b/src/main/java/org/apache/maven/plugin/surefire/report/Theme.java index 4e2ef01..fd57138 100644 --- a/src/main/java/org/apache/maven/plugin/surefire/report/Theme.java +++ b/src/main/java/org/apache/maven/plugin/surefire/report/Theme.java @@ -38,6 +38,7 @@ public enum Theme { * [INFO] +--Nested Sample * [INFO] | +-- [OK] Should pass - 0.03s * [INFO] | '-- [OK] Should pass2 - 0.002s + * [INFO] | '-- [XX] Should fail - 0.005s * [INFO] +--,--Inner Test * [INFO] | | '-- [OK] Inner test should pass - 0.001s * [INFO] | '--,--Inner Inner Test @@ -49,9 +50,16 @@ public enum Theme { * [INFO] | +-- [OK] Should pass again - 0.001s * [INFO] | +-- [OK] Should pass for the 3rd time - 0.001s * [INFO] | '-- [OK] Should pass for the 4th time - 0s + * [INFO] [*] Should fail + * [INFO] Stack trace + * ... + * [INFO] Standard out + * ... + * [INFO] Standard error + * ... * */ - ASCII("| ", "+--", "'--", ".--", "---", " [OK] ", " [XX] ", " [??] "), + ASCII("| ", "+--", "'--", ".--", "---", " [OK] ", " [XX] ", " [??] ", "[*] "), /** * Unicode (extended ASCII) characters are used to display the test execution tree. @@ -61,6 +69,7 @@ public enum Theme { * [INFO] ├─ Nested Sample * [INFO] │ ├─ ✔ Should pass - 0.013s * [INFO] │ └─ ✔ Should pass2 - 0.001s + * [INFO] │ └─ ✘ Should fail - 0.003s * [INFO] ├─ ┬─ Inner Test * [INFO] │ │ └─ ✔ Inner test should pass - 0.001s * [INFO] │ └─ ┬─ Inner Inner Test @@ -72,9 +81,16 @@ public enum Theme { * [INFO] │ ├─ ✔ Should pass again - 0.001s * [INFO] │ ├─ ✔ Should pass for the 3rd time - 0s * [INFO] │ └─ ✔ Should pass for the 4th time - 0s + * [INFO] ● Should fail + * [INFO] Stack trace + * ... + * [INFO] Standard out + * ... + * [INFO] Standard error + * ... * */ - UNICODE("│ ", "├─ ", "└─ ", "┬─ ", "── ", "✔ ", "✘ ", "↷ "); + UNICODE("│ ", "├─ ", "└─ ", "┬─ ", "── ", "✔ ", "✘ ", "↷ ", "● "); public static Theme valueOf(Charset charset) { if (StandardCharsets.UTF_8.equals(charset)) { @@ -126,6 +142,10 @@ public final String skipped() { return tiles[7]; } + public final String details() { + return tiles[8]; + } + /** * Return lower case {@link #name()} for easier usage in help text for * available options. @@ -134,4 +154,5 @@ public final String skipped() { public final String toString() { return name().toLowerCase(); } + } 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 5a92160..8d330f3 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 @@ -1,5 +1,17 @@ package org.apache.maven.plugin.surefire.report; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; +import static org.apache.maven.plugin.surefire.report.TestSetStats.concatenateWithTestGroup; +import static org.apache.maven.plugin.surefire.report.TextFormatter.abbreviateName; +import static org.apache.maven.surefire.shared.utils.StringUtils.isBlank; +import static org.apache.maven.surefire.shared.utils.logging.MessageUtils.buffer; + +import java.io.IOException; +import java.util.List; +import java.util.Set; +import java.util.stream.LongStream; + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -20,19 +32,9 @@ */ import org.apache.maven.plugin.surefire.log.api.ConsoleLogger; +import org.apache.maven.surefire.shared.lang3.StringUtils; import org.apache.maven.surefire.shared.utils.logging.MessageBuilder; -import java.util.List; -import java.util.Set; -import java.util.stream.LongStream; - -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toSet; -import static org.apache.maven.plugin.surefire.report.TestSetStats.concatenateWithTestGroup; -import static org.apache.maven.plugin.surefire.report.TextFormatter.abbreviateName; -import static org.apache.maven.surefire.shared.utils.StringUtils.isBlank; -import static org.apache.maven.surefire.shared.utils.logging.MessageUtils.buffer; - /** * Tree view printer. * @@ -45,20 +47,16 @@ public class TreePrinter { private final List testSetStats; private final List sourceNames; private final Set distinctSourceName; - private final Theme theme; + private final ReporterOptions options; private static final int $ = 36; - public TreePrinter(ConsoleLogger consoleLogger, List classResults, List testSetStats, Theme theme) { + public TreePrinter(ConsoleLogger consoleLogger, List classResults, List testSetStats, ReporterOptions options) { this.consoleLogger = consoleLogger; this.classResults = classResults; this.testSetStats = testSetStats; this.sourceNames = getSourceNames(); this.distinctSourceName = getDistinctSourceNames(); - this.theme = theme; - } - - public TreePrinter(ConsoleLogger consoleLogger, List classResults, List testSetStats) { - this(consoleLogger, classResults, testSetStats, Theme.ASCII); + this.options = options; } private List getSourceNames() { @@ -80,18 +78,51 @@ public void printTests() { .stream() .map(TestPrinter::new) .forEach(TestPrinter::printTest); + testSetStats + .stream() + .map(TestPrinter::new) + .forEach(TestPrinter::printDetails); } private class TestPrinter { private final WrappedReportEntry testResult; private final int treeLength; + private final Theme theme = options.getTheme(); public TestPrinter(WrappedReportEntry testResult) { this.testResult = testResult; this.treeLength = getTreeLength(); } + private void printDetails() { + boolean isSuccess = testResult.getReportEntryType() == ReportEntryType.SUCCESS; + boolean isError = testResult.getReportEntryType() == ReportEntryType.ERROR; + boolean isFailure = testResult.getReportEntryType() == ReportEntryType.FAILURE; + + boolean printStackTrace = options.isPrintStacktraceOnError() && isError + || options.isPrintStacktraceOnFailure() && isFailure; + boolean printStdOut = options.isPrintStdoutOnSuccess() && isSuccess + || options.isPrintStdoutOnError() && isError + || options.isPrintStdoutOnFailure() && isFailure; + boolean printStdErr = options.isPrintStderrOnSuccess() && isSuccess + || options.isPrintStderrOnError() && isError + || options.isPrintStderrOnFailure() && isFailure; + + if (printStackTrace || printStdOut || printStdErr) { + printPreambleDetails(); + if (printStackTrace) { + printStackTrace(); + } + if (printStdOut) { + printStdOut(); + } + if (printStdErr) { + printStdErr(); + } + } + } + private void printTest() { printClass(); if (testResult.isErrorOrFailure()) { @@ -107,7 +138,7 @@ private void printSuccess() { println(buffer() .success(theme.successful() + abbreviateName(testResult.getReportName()))); } - + private void printSkipped() { println(buffer() .warning(theme.skipped() + getSkippedReport()) @@ -130,6 +161,45 @@ private String getSkippedMessage() { } } + private void printPreambleDetails() { + println(""); + if (testResult.isSucceeded()) { + println(buffer().success(theme.details()).success(abbreviateName(testResult.getReportName())).toString()); + } else { + println(buffer().failure(theme.details()).failure(abbreviateName(testResult.getReportName())).toString()); + } + } + + private void printStdOut() { + println(""); + println(buffer().strong("Standard out").toString()); + try { + testResult.getStdout().writeTo(System.out); + } + catch (final IOException ignored) {} + } + + private void printStdErr() { + println(""); + println(buffer().strong("Standard error").toString()); + try { + testResult.getStdErr().writeTo(System.err); + } + catch (final IOException ignored) {} + } + + private void printStackTrace() { + println(""); + println(buffer().strong("Stack trace").toString()); + String stackTrace = testResult.getStackTrace(false); + if (stackTrace != null && !StringUtils.isBlank(stackTrace)) { + println(testResult.getStackTrace(false)); + } + else { + println("[No stack trace available]"); + } + } + private void printFailure() { println(buffer() .failure(theme.failed() + abbreviateName(testResult.getReportName()))); diff --git a/src/test/java/DynamicExampleTest.java b/src/test/java/DynamicExampleTest.java new file mode 100644 index 0000000..bf4e9ba --- /dev/null +++ b/src/test/java/DynamicExampleTest.java @@ -0,0 +1,28 @@ +import org.junit.jupiter.api.*; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DynamicExampleTest { + + Collection tests = Arrays.asList( + DynamicTest.dynamicTest("Add test", + () -> assertEquals(2, Math.addExact(1, 1))), + DynamicTest.dynamicTest("Multiply Test", + () -> assertEquals(4, Math.multiplyExact(2, 2)))); + + @TestFactory + Collection dynamicTestsWithCollection() { + return tests; + } + + @TestFactory + @DisplayName("Calculating") + Collection dynamicTestsWithCollectionWithDisplayName() { + return tests; + } + +} 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 2d40815..ff4de5c 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 @@ -35,7 +35,7 @@ void testSetStarting() { 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 consoleTreeReporter = new ConsoleTreeReporter(new PluginConsoleLogger(logger), ReporterOptions.builder().build()); consoleTreeReporter.testSetStarting(simpleReportEntry1); consoleTreeReporter.testSetStarting(simpleReportEntry2); consoleTreeReporter.testSetStarting(simpleReportEntry3); @@ -77,7 +77,7 @@ void testSetCompleted() { TestSetStats testSetStatsForClass = new TestSetStats(false, true); - ConsoleTreeReporterAscii consoleTreeReporter = new ConsoleTreeReporterAscii(new PluginConsoleLogger(logger), false, false); + ConsoleTreeReporter consoleTreeReporter = new ConsoleTreeReporter(new PluginConsoleLogger(logger), ReporterOptions.builder().build()); consoleTreeReporter.testSetStarting(simpleReportEntry1); consoleTreeReporter.testSetStarting(simpleReportEntry2); consoleTreeReporter.testSetStarting(simpleReportEntry3);