You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2018/12/23 16:17:51 UTC
[maven-surefire] 01/01: [SUREFIRE-1546] JUnit 5 runner does not
honor JUnit 5 display names
This is an automated email from the ASF dual-hosted git repository.
tibordigana pushed a commit to branch SUREFIRE-1546-dispname
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
commit c5e93878a0abc317c2b402c415adfacc435929fa
Author: Tibor17 <ti...@apache.org>
AuthorDate: Sat Dec 22 10:53:40 2018 +0100
[SUREFIRE-1546] JUnit 5 runner does not honor JUnit 5 display names
---
.../surefire/runorder/RunEntryStatisticsMap.java | 20 +---
.../util/internal/TestClassMethodNameUtils.java | 21 ++--
.../maven/surefire/its/JUnitPlatformEnginesIT.java | 3 +-
.../test/java/junitplatform/DisplayNameTest.java | 37 +++++++
.../surefire/junitplatform/RunListenerAdapter.java | 114 +++++++++------------
5 files changed, 97 insertions(+), 98 deletions(-)
diff --git a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java
index 1a685dc..40d396b 100644
--- a/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java
+++ b/surefire-api/src/main/java/org/apache/maven/plugin/surefire/runorder/RunEntryStatisticsMap.java
@@ -19,7 +19,6 @@ package org.apache.maven.plugin.surefire.runorder;
* under the License.
*/
-
import org.apache.maven.surefire.report.ReportEntry;
import java.io.BufferedReader;
@@ -36,12 +35,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import static java.util.Collections.sort;
import static org.apache.maven.plugin.surefire.runorder.RunEntryStatistics.fromReportEntry;
import static org.apache.maven.plugin.surefire.runorder.RunEntryStatistics.fromString;
+import static org.apache.maven.surefire.util.internal.TestClassMethodNameUtils.extractClassName;
/**
* @author Kristian Rosenvold
@@ -50,7 +48,7 @@ public final class RunEntryStatisticsMap
{
private final Map<String, RunEntryStatistics> runEntryStatistics;
- public RunEntryStatisticsMap( Map<String, RunEntryStatistics> runEntryStatistics )
+ private RunEntryStatisticsMap( Map<String, RunEntryStatistics> runEntryStatistics )
{
this.runEntryStatistics = new ConcurrentHashMap<>( runEntryStatistics );
}
@@ -112,7 +110,7 @@ public final class RunEntryStatisticsMap
}
}
- public RunEntryStatistics findOrCreate( ReportEntry reportEntry )
+ private RunEntryStatistics findOrCreate( ReportEntry reportEntry )
{
final RunEntryStatistics item = runEntryStatistics.get( reportEntry.getName() );
return item != null ? item : fromReportEntry( reportEntry );
@@ -255,16 +253,4 @@ public final class RunEntryStatisticsMap
return o.getMinSuccessRate() - o1.getMinSuccessRate();
}
}
-
-
- private static final Pattern PARENS = Pattern.compile( "^" + "[^\\(\\)]+" //non-parens
- + "\\((" // then an open-paren (start matching a group)
- + "[^\\\\(\\\\)]+" //non-parens
- + ")\\)" + "$" ); // then a close-paren (end group match)
-
- String extractClassName( String displayName )
- {
- Matcher m = PARENS.matcher( displayName );
- return m.find() ? m.group( 1 ) : displayName;
- }
}
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/TestClassMethodNameUtils.java b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/TestClassMethodNameUtils.java
index 23e72e1..3371993 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/TestClassMethodNameUtils.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/util/internal/TestClassMethodNameUtils.java
@@ -19,9 +19,6 @@ package org.apache.maven.surefire.util.internal;
* under the License.
*/
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
/**
* JUnit Description parser.
* Used by JUnit Version lower than 4.7.
@@ -31,12 +28,6 @@ import java.util.regex.Pattern;
*/
public final class TestClassMethodNameUtils
{
- /**
- * This pattern is verbatim copy from JUnit's code in class {@code Description}.
- * Parsing class and method from junit description would provide identical result to JUnit internal parser.
- */
- private static final Pattern METHOD_CLASS_PATTERN = Pattern.compile( "([\\s\\S]*)\\((.*)\\)" );
-
private TestClassMethodNameUtils()
{
throw new IllegalStateException( "no instantiable constructor" );
@@ -44,13 +35,17 @@ public final class TestClassMethodNameUtils
public static String extractClassName( String displayName )
{
- Matcher m = METHOD_CLASS_PATTERN.matcher( displayName );
- return m.matches() ? m.group( 2 ) : displayName;
+ if ( displayName.endsWith( ")" ) )
+ {
+ int paren = displayName.lastIndexOf( '(' );
+ return paren == -1 ? displayName : displayName.substring( paren + 1, displayName.length() - 1 );
+ }
+ return displayName;
}
public static String extractMethodName( String displayName )
{
- Matcher m = METHOD_CLASS_PATTERN.matcher( displayName );
- return m.matches() ? m.group( 1 ) : displayName;
+ int paren = displayName.lastIndexOf( '(' );
+ return paren == -1 ? displayName : displayName.substring( 0, paren );
}
}
diff --git a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformEnginesIT.java b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformEnginesIT.java
index 332cbb9..3c07777 100644
--- a/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformEnginesIT.java
+++ b/surefire-its/src/test/java/org/apache/maven/surefire/its/JUnitPlatformEnginesIT.java
@@ -63,6 +63,7 @@ public class JUnitPlatformEnginesIT
args.add( new Object[] { "1.1.1", "5.1.1", "1.0.0", "1.0.0" } );
args.add( new Object[] { "1.2.0", "5.2.0", "1.1.0", "1.0.0" } );
args.add( new Object[] { "1.3.1", "5.3.1", "1.1.1", "1.0.0" } );
+ args.add( new Object[] { "1.3.2", "5.3.2", "1.1.1", "1.0.0" } );
args.add( new Object[] { "1.4.0-SNAPSHOT", "5.4.0-SNAPSHOT", "1.1.1", "1.0.0" } );
return args;
}
@@ -88,7 +89,7 @@ public class JUnitPlatformEnginesIT
.sysProp( "jupiter.version", jupiter )
.debugLogging()
.executeTest()
- .verifyErrorFree( 1 );
+ .verifyErrorFree( 2 );
String testClasspath = "[DEBUG] test(compact) classpath:"
+ " test-classes"
diff --git a/surefire-its/src/test/resources/junit-platform/src/test/java/junitplatform/DisplayNameTest.java b/surefire-its/src/test/resources/junit-platform/src/test/java/junitplatform/DisplayNameTest.java
new file mode 100644
index 0000000..f47dfa1
--- /dev/null
+++ b/surefire-its/src/test/resources/junit-platform/src/test/java/junitplatform/DisplayNameTest.java
@@ -0,0 +1,37 @@
+package junitplatform_1_0_0;
+
+/*
+ * 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.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.logging.Logger;
+
+class DisplayNameTest
+{
+ private static final Logger LOGGER = Logger.getLogger( DisplayNameTest.class.getName() );
+
+ @Test
+ @DisplayName( "Custom test name containing spaces" )
+ void test()
+ {
+ LOGGER.warning( "some warning from test" );
+ }
+}
diff --git a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java
index 85227f3..c2810f1 100644
--- a/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java
+++ b/surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/RunListenerAdapter.java
@@ -20,6 +20,9 @@ package org.apache.maven.surefire.junitplatform;
*/
import static org.apache.maven.surefire.report.SimpleReportEntry.ignored;
+import static org.apache.maven.surefire.report.SimpleReportEntry.withException;
+import static org.apache.maven.surefire.util.internal.TestClassMethodNameUtils.extractClassName;
+import static org.apache.maven.surefire.util.internal.TestClassMethodNameUtils.extractMethodName;
import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED;
import static org.junit.platform.engine.TestExecutionResult.Status.FAILED;
@@ -38,7 +41,6 @@ import org.junit.platform.engine.support.descriptor.MethodSource;
import org.junit.platform.launcher.TestExecutionListener;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
-import org.junit.platform.launcher.listeners.LegacyReportingUtils;
/**
* @since 2.22.0
@@ -46,12 +48,11 @@ import org.junit.platform.launcher.listeners.LegacyReportingUtils;
final class RunListenerAdapter
implements TestExecutionListener
{
-
private final RunListener runListener;
- private TestPlan testPlan;
+ private final Set<TestIdentifier> testSetNodes = ConcurrentHashMap.newKeySet();
- private Set<TestIdentifier> testSetNodes = ConcurrentHashMap.newKeySet();
+ private volatile TestPlan testPlan;
RunListenerAdapter( RunListener runListener )
{
@@ -89,14 +90,15 @@ final class RunListenerAdapter
public void executionSkipped( TestIdentifier testIdentifier, String reason )
{
ensureTestSetStarted( testIdentifier );
- String source = getLegacyReportingClassName( testIdentifier );
- runListener.testSkipped( ignored( source, getLegacyReportingName( testIdentifier ), reason ) );
+ String[] classMethodName = toClassMethodName( testIdentifier );
+ String className = classMethodName[0];
+ String methodName = classMethodName[1];
+ runListener.testSkipped( ignored( className, methodName, reason ) );
completeTestSetIfNecessary( testIdentifier );
}
@Override
- public void executionFinished(
- TestIdentifier testIdentifier, TestExecutionResult testExecutionResult )
+ public void executionFinished( TestIdentifier testIdentifier, TestExecutionResult testExecutionResult )
{
if ( testExecutionResult.getStatus() == ABORTED )
{
@@ -121,17 +123,11 @@ final class RunListenerAdapter
private void ensureTestSetStarted( TestIdentifier testIdentifier )
{
- if ( isTestSetStarted( testIdentifier ) )
- {
- return;
- }
- if ( testIdentifier.isTest() )
- {
- startTestSet( testPlan.getParent( testIdentifier ).orElse( testIdentifier ) );
- }
- else
+ if ( !isTestSetStarted( testIdentifier ) )
{
- startTestSet( testIdentifier );
+ startTestSet( testIdentifier.isTest()
+ ? testPlan.getParent( testIdentifier ).orElse( testIdentifier )
+ : testIdentifier );
}
}
@@ -185,8 +181,10 @@ final class RunListenerAdapter
private SimpleReportEntry createTestSetReportEntry( TestIdentifier testIdentifier )
{
- return new SimpleReportEntry(
- JUnitPlatformProvider.class.getName(), testIdentifier.getLegacyReportingName() );
+ String[] classMethodName = toClassMethodName( testIdentifier );
+ String className = classMethodName[0];
+ String methodName = classMethodName[1];
+ return new SimpleReportEntry( className, methodName );
}
private SimpleReportEntry createReportEntry( TestIdentifier testIdentifier )
@@ -194,79 +192,61 @@ final class RunListenerAdapter
return createReportEntry( testIdentifier, (StackTraceWriter) null );
}
- private SimpleReportEntry createReportEntry(
- TestIdentifier testIdentifier, TestExecutionResult testExecutionResult )
- {
- return createReportEntry(
- testIdentifier, getStackTraceWriter( testIdentifier, testExecutionResult ) );
- }
-
- private SimpleReportEntry createReportEntry(
- TestIdentifier testIdentifier, StackTraceWriter stackTraceWriter )
- {
- String source = getLegacyReportingClassName( testIdentifier );
- String name = getLegacyReportingName( testIdentifier );
-
- return SimpleReportEntry.withException( source, name, stackTraceWriter );
- }
-
- private String getLegacyReportingName( TestIdentifier testIdentifier )
+ private SimpleReportEntry createReportEntry( TestIdentifier testIdentifier,
+ TestExecutionResult testExecutionResult )
{
- // Surefire cuts off the name at the first '(' character. Thus, we have to pick a different
- // character to represent parentheses. "()" are removed entirely to maximize compatibility with
- // existing reporting tools because in the old days test methods used to not have parameters.
- return testIdentifier
- .getLegacyReportingName()
- .replace( "()", "" )
- .replace( '(', '{' )
- .replace( ')', '}' );
+ return createReportEntry( testIdentifier, toStackTraceWriter( testIdentifier, testExecutionResult ) );
}
- private String getLegacyReportingClassName( TestIdentifier testIdentifier )
+ private SimpleReportEntry createReportEntry( TestIdentifier testIdentifier, StackTraceWriter stackTraceWriter )
{
- return LegacyReportingUtils.getClassName( testPlan, testIdentifier );
+ String[] classMethodName = toClassMethodName( testIdentifier );
+ String className = classMethodName[0];
+ String methodName = classMethodName[1];
+ return withException( className, methodName, stackTraceWriter );
}
- private StackTraceWriter getStackTraceWriter(
- TestIdentifier testIdentifier, TestExecutionResult testExecutionResult )
+ private StackTraceWriter toStackTraceWriter( TestIdentifier testIdentifier,
+ TestExecutionResult testExecutionResult )
{
Optional<Throwable> throwable = testExecutionResult.getThrowable();
if ( testExecutionResult.getStatus() == FAILED )
{
// Failed tests must have a StackTraceWriter, otherwise Surefire will fail
- return getStackTraceWriter( testIdentifier, throwable.orElse( null ) );
+ return toStackTraceWriter( testIdentifier, throwable.orElse( null ) );
}
- return throwable.map( t -> getStackTraceWriter( testIdentifier, t ) ).orElse( null );
+ return throwable.map( t -> toStackTraceWriter( testIdentifier, t ) )
+ .orElse( null );
}
- private StackTraceWriter getStackTraceWriter( TestIdentifier testIdentifier, Throwable throwable )
+ private StackTraceWriter toStackTraceWriter( TestIdentifier testIdentifier, Throwable throwable )
{
- String className = getClassName( testIdentifier );
- String methodName = getMethodName( testIdentifier ).orElse( "" );
+ String[] classMethodName = toClassMethodName( testIdentifier );
+ String className = classMethodName[0];
+ String methodName = classMethodName[1];
return new PojoStackTraceWriter( className, methodName, throwable );
}
- private String getClassName( TestIdentifier testIdentifier )
+ private String[] toClassMethodName( TestIdentifier testIdentifier )
{
+ String methodDisplayName = testIdentifier.getDisplayName();
TestSource testSource = testIdentifier.getSource().orElse( null );
if ( testSource instanceof ClassSource )
{
- return ( (ClassSource) testSource ).getJavaClass().getName();
+ ClassSource classSource = (ClassSource) testSource;
+ return new String[] { classSource.getClassName(), methodDisplayName };
}
- if ( testSource instanceof MethodSource )
+ else if ( testSource instanceof MethodSource )
{
- return ( (MethodSource) testSource ).getClassName();
+ MethodSource methodSource = (MethodSource) testSource;
+ return new String[] { methodSource.getClassName(), methodDisplayName };
}
- return testPlan.getParent( testIdentifier ).map( this::getClassName ).orElse( "" );
- }
-
- private Optional<String> getMethodName( TestIdentifier testIdentifier )
- {
- TestSource testSource = testIdentifier.getSource().orElse( null );
- if ( testSource instanceof MethodSource )
+ else
{
- return Optional.of( ( (MethodSource) testSource ).getMethodName() );
+ String description = testIdentifier.getLegacyReportingName();
+ return testPlan.getParent( testIdentifier )
+ .map( this::toClassMethodName )
+ .orElse( new String[] { extractClassName( description ), extractMethodName( description ) } );
}
- return Optional.empty();
}
}