Repository: maven-surefire
Updated Branches:
  refs/heads/junit5 e4a5247a7 -> 9580f5ef2


SUREFIRE-1330: Import code from 
https://issues.apache.org/jira/browse/SUREFIRE-1330 unchanged as provided


Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/4bf43aab
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/4bf43aab
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/4bf43aab

Branch: refs/heads/junit5
Commit: 4bf43aab9726f387a35bff40ee0c872110e03d52
Parents: e4a5247
Author: Benedikt Ritter <brit...@apache.org>
Authored: Mon Feb 6 14:02:48 2017 +0100
Committer: Benedikt Ritter <brit...@apache.org>
Committed: Mon Jun 12 08:18:29 2017 +0200

----------------------------------------------------------------------
 surefire-providers/surefire-junit5/LICENSE.md   | 194 +++++++++++++
 .../provider/JUnitPlatformProvider.java         | 170 +++++++++++
 .../surefire/provider/RunListenerAdapter.java   | 124 ++++++++
 .../provider/TestPlanScannerFilter.java         |  56 ++++
 .../surefire/provider/package-info.java         |   5 +
 ....maven.surefire.providerapi.SurefireProvider |   1 +
 .../provider/JUnitPlatformProviderTests.java    | 286 +++++++++++++++++++
 .../provider/RunListenerAdapterTests.java       | 219 ++++++++++++++
 .../provider/SurefireProviderTestSuite.java     |  45 +++
 .../provider/TestPlanScannerFilterTests.java    | 157 ++++++++++
 .../src/test/resources/log4j2-test.xml          |  15 +
 11 files changed, 1272 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/4bf43aab/surefire-providers/surefire-junit5/LICENSE.md
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit5/LICENSE.md 
b/surefire-providers/surefire-junit5/LICENSE.md
new file mode 100644
index 0000000..b62a9b5
--- /dev/null
+++ b/surefire-providers/surefire-junit5/LICENSE.md
@@ -0,0 +1,194 @@
+Apache License
+==============
+
+_Version 2.0, January 2004_
+_&lt;<http://www.apache.org/licenses/>&gt;_
+
+### Terms and Conditions for use, reproduction, and distribution
+
+#### 1. Definitions
+
+“License” shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+“Licensor” shall mean the copyright owner or entity authorized by the 
copyright
+owner that is granting the License.
+
+“Legal Entity” shall mean the union of the acting entity and all other 
entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, “control” means **(i)** the power, 
direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of 
the
+outstanding shares, or **(iii)** beneficial ownership of such entity.
+
+“You” (or “Your”) shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+“Source” form shall mean the preferred form for making modifications, 
including
+but not limited to software source code, documentation source, and 
configuration
+files.
+
+“Object” form shall mean any form resulting from mechanical transformation 
or
+translation of a Source form, including but not limited to compiled object 
code,
+generated documentation, and conversions to other media types.
+
+“Work” shall mean the work of authorship, whether in Source or Object 
form, made
+available under the License, as indicated by a copyright notice that is 
included
+in or attached to the work (an example is provided in the Appendix below).
+
+“Derivative Works” shall mean any work, whether in Source or Object form, 
that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+“Contribution” shall mean any work of authorship, including the original 
version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+“submitted” means any form of electronic, verbal, or written communication 
sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the 
copyright
+owner as “Not a Contribution.”
+
+“Contributor” shall mean Licensor and any individual or Legal Entity on 
behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+#### 2. Grant of Copyright License
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and 
such
+Derivative Works in Source or Object form.
+
+#### 3. Grant of Patent License
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+#### 4. Redistribution
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+* **(a)** You must give any other recipients of the Work or Derivative Works a 
copy of
+this License; and
+* **(b)** You must cause any modified files to carry prominent notices stating 
that You
+changed the files; and
+* **(c)** You must retain, in the Source form of any Derivative Works that You 
distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+* **(d)** If the Work includes a “NOTICE” text file as part of its 
distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents 
of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a 
whole,
+provided Your use, reproduction, and distribution of the Work otherwise 
complies
+with the conditions stated in this License.
+
+#### 5. Submission of Contributions
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms 
of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+#### 6. Trademarks
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+#### 7. Disclaimer of Warranty
+
+Unless required by applicable law or agreed to in writing, Licensor provides 
the
+Work (and each Contributor provides its Contributions) on an “AS IS” BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+#### 8. Limitation of Liability
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License 
or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, 
or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+#### 9. Accepting Warranty or Additional Liability
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. 
However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any 
liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+_END OF TERMS AND CONDITIONS_
+
+### APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate
+notice, with the fields enclosed by brackets `[]` replaced with your own
+identifying information. (Don't include the brackets!) The text should be
+enclosed in the appropriate comment syntax for the file format. We also
+recommend that a file or class name and description of purpose be included on
+the same “printed page” as the copyright notice for easier identification 
within
+third-party archives.
+
+    Copyright [yyyy] [name of copyright owner]
+
+    Licensed 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.

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/4bf43aab/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/JUnitPlatformProvider.java
----------------------------------------------------------------------
diff --git 
a/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/JUnitPlatformProvider.java
 
b/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/JUnitPlatformProvider.java
new file mode 100644
index 0000000..676d33f
--- /dev/null
+++ 
b/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/JUnitPlatformProvider.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2015-2017 the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.junit.platform.surefire.provider;
+
+import static 
org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
+import static 
org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.maven.surefire.providerapi.AbstractProvider;
+import org.apache.maven.surefire.providerapi.ProviderParameters;
+import org.apache.maven.surefire.report.ReporterException;
+import org.apache.maven.surefire.report.ReporterFactory;
+import org.apache.maven.surefire.report.RunListener;
+import org.apache.maven.surefire.report.SimpleReportEntry;
+import org.apache.maven.surefire.suite.RunResult;
+import org.apache.maven.surefire.testset.TestSetFailedException;
+import org.apache.maven.surefire.util.TestsToRun;
+import org.junit.platform.commons.util.Preconditions;
+import org.junit.platform.engine.Filter;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TagFilter;
+import org.junit.platform.launcher.core.LauncherFactory;
+
+/**
+ * @since 1.0
+ */
+public class JUnitPlatformProvider extends AbstractProvider {
+
+       // Parameter names processed to determine which @Tags should be 
executed.
+       static final String EXCLUDE_GROUPS = "excludedGroups";
+       static final String EXCLUDE_TAGS = "excludeTags";
+       static final String INCLUDE_GROUPS = "groups";
+       static final String INCLUDE_TAGS = "includeTags";
+
+       static final String EXCEPTION_MESSAGE_BOTH_NOT_ALLOWED = "The " + 
INCLUDE_GROUPS + " and " + INCLUDE_TAGS
+                       + " parameters (or the " + EXCLUDE_GROUPS + " and " + 
EXCLUDE_TAGS + " parameters) are synonyms - "
+                       + "only one of each is allowed (though neither is 
required).";
+
+       private final ProviderParameters parameters;
+       private final Launcher launcher;
+       final Filter<?>[] includeAndExcludeFilters;
+
+       public JUnitPlatformProvider(ProviderParameters parameters) {
+               this(parameters, LauncherFactory.create());
+       }
+
+       JUnitPlatformProvider(ProviderParameters parameters, Launcher launcher) 
{
+               this.parameters = parameters;
+               this.launcher = launcher;
+               this.includeAndExcludeFilters = getIncludeAndExcludeFilters();
+               Logger.getLogger("org.junit").setLevel(Level.WARNING);
+       }
+
+       @Override
+       public Iterable<Class<?>> getSuites() {
+               return scanClasspath();
+       }
+
+       @Override
+       public RunResult invoke(Object forkTestSet)
+                       throws TestSetFailedException, ReporterException, 
InvocationTargetException {
+               if (forkTestSet instanceof TestsToRun) {
+                       return invokeAllTests((TestsToRun) forkTestSet);
+               }
+               else if (forkTestSet instanceof Class) {
+                       return invokeAllTests(TestsToRun.fromClass((Class<?>) 
forkTestSet));
+               }
+               else if (forkTestSet == null) {
+                       return invokeAllTests(scanClasspath());
+               }
+               else {
+                       throw new IllegalArgumentException("Unexpected value of 
forkTestSet: " + forkTestSet);
+               }
+       }
+
+       private TestsToRun scanClasspath() {
+               TestsToRun scannedClasses = 
parameters.getScanResult().applyFilter(
+                       new TestPlanScannerFilter(launcher, 
includeAndExcludeFilters), parameters.getTestClassLoader());
+               return 
parameters.getRunOrderCalculator().orderTestClasses(scannedClasses);
+       }
+
+       private RunResult invokeAllTests(TestsToRun testsToRun) {
+               RunResult runResult;
+               ReporterFactory reporterFactory = 
parameters.getReporterFactory();
+               try {
+                       RunListener runListener = 
reporterFactory.createReporter();
+                       launcher.registerTestExecutionListeners(new 
RunListenerAdapter(runListener));
+
+                       for (Class<?> testClass : testsToRun) {
+                               invokeSingleClass(testClass, runListener);
+                       }
+               }
+               finally {
+                       runResult = reporterFactory.close();
+               }
+               return runResult;
+       }
+
+       private void invokeSingleClass(Class<?> testClass, RunListener 
runListener) {
+               SimpleReportEntry classEntry = new 
SimpleReportEntry(getClass().getName(), testClass.getName());
+               runListener.testSetStarting(classEntry);
+
+               LauncherDiscoveryRequest discoveryRequest = 
request().selectors(selectClass(testClass)).filters(
+                       includeAndExcludeFilters).build();
+               launcher.execute(discoveryRequest);
+
+               runListener.testSetCompleted(classEntry);
+       }
+
+       private Filter<?>[] getIncludeAndExcludeFilters() {
+               List<Filter<?>> filters = new ArrayList<>();
+
+               Optional<List<String>> includes = 
getGroupsOrTags(getPropertiesList(INCLUDE_GROUPS),
+                       getPropertiesList(INCLUDE_TAGS));
+               includes.map(TagFilter::includeTags).ifPresent(filters::add);
+
+               Optional<List<String>> excludes = 
getGroupsOrTags(getPropertiesList(EXCLUDE_GROUPS),
+                       getPropertiesList(EXCLUDE_TAGS));
+               excludes.map(TagFilter::excludeTags).ifPresent(filters::add);
+
+               return filters.toArray(new Filter<?>[filters.size()]);
+       }
+
+       private Optional<List<String>> getPropertiesList(String key) {
+               List<String> compoundProperties = null;
+               String property = parameters.getProviderProperties().get(key);
+               if (property != null) {
+                       compoundProperties = Arrays.asList(property.split("[, 
]+"));
+               }
+               return Optional.ofNullable(compoundProperties);
+       }
+
+       private Optional<List<String>> getGroupsOrTags(Optional<List<String>> 
groups, Optional<List<String>> tags) {
+               Optional<List<String>> elements = Optional.empty();
+
+               Preconditions.condition(!groups.isPresent() || 
!tags.isPresent(), EXCEPTION_MESSAGE_BOTH_NOT_ALLOWED);
+
+               if (groups.isPresent()) {
+                       elements = groups;
+               }
+               else if (tags.isPresent()) {
+                       elements = tags;
+               }
+
+               return elements;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/4bf43aab/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/RunListenerAdapter.java
----------------------------------------------------------------------
diff --git 
a/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/RunListenerAdapter.java
 
b/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/RunListenerAdapter.java
new file mode 100644
index 0000000..70fb928
--- /dev/null
+++ 
b/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/RunListenerAdapter.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2015-2017 the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.junit.platform.surefire.provider;
+
+import static org.apache.maven.surefire.report.SimpleReportEntry.ignored;
+import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED;
+import static org.junit.platform.engine.TestExecutionResult.Status.FAILED;
+
+import java.util.Optional;
+
+import org.apache.maven.surefire.report.PojoStackTraceWriter;
+import org.apache.maven.surefire.report.RunListener;
+import org.apache.maven.surefire.report.SimpleReportEntry;
+import org.apache.maven.surefire.report.StackTraceWriter;
+import org.junit.platform.engine.TestExecutionResult;
+import org.junit.platform.engine.TestSource;
+import org.junit.platform.engine.support.descriptor.ClassSource;
+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;
+
+/**
+ * @since 1.0
+ */
+final class RunListenerAdapter implements TestExecutionListener {
+
+       private final RunListener runListener;
+       private Optional<TestPlan> testPlan = Optional.empty();
+
+       public RunListenerAdapter(RunListener runListener) {
+               this.runListener = runListener;
+       }
+
+       @Override
+       public void testPlanExecutionStarted(TestPlan testPlan) {
+               this.testPlan = Optional.of(testPlan);
+       }
+
+       @Override
+       public void testPlanExecutionFinished(TestPlan testPlan) {
+               this.testPlan = Optional.empty();
+       }
+
+       @Override
+       public void executionStarted(TestIdentifier testIdentifier) {
+               if (testIdentifier.isTest()) {
+                       
runListener.testStarting(createReportEntry(testIdentifier, Optional.empty()));
+               }
+       }
+
+       @Override
+       public void executionSkipped(TestIdentifier testIdentifier, String 
reason) {
+               String source = getClassName(testIdentifier).orElseGet(() -> 
parentDisplayName(testIdentifier));
+               runListener.testSkipped(ignored(source, 
testIdentifier.getDisplayName(), reason));
+       }
+
+       @Override
+       public void executionFinished(TestIdentifier testIdentifier, 
TestExecutionResult testExecutionResult) {
+               if (testExecutionResult.getStatus() == ABORTED) {
+                       
runListener.testAssumptionFailure(createReportEntry(testIdentifier, 
testExecutionResult.getThrowable()));
+               }
+               else if (testExecutionResult.getStatus() == FAILED) {
+                       
runListener.testFailed(createReportEntry(testIdentifier, 
testExecutionResult.getThrowable()));
+               }
+               else if (testIdentifier.isTest()) {
+                       
runListener.testSucceeded(createReportEntry(testIdentifier, Optional.empty()));
+               }
+       }
+
+       private SimpleReportEntry createReportEntry(TestIdentifier 
testIdentifier, Optional<Throwable> throwable) {
+               Optional<String> className = getClassName(testIdentifier);
+               if (className.isPresent()) {
+                       StackTraceWriter traceWriter = new 
PojoStackTraceWriter(className.get(),
+                               getMethodName(testIdentifier).orElse(""), 
throwable.orElse(null));
+                       return new SimpleReportEntry(className.get(), 
testIdentifier.getDisplayName(), traceWriter, null);
+               }
+               else {
+                       return new 
SimpleReportEntry(parentDisplayName(testIdentifier), 
testIdentifier.getDisplayName(), null);
+               }
+       }
+
+       private Optional<String> getClassName(TestIdentifier testIdentifier) {
+               TestSource testSource = testIdentifier.getSource().orElse(null);
+               if (testSource instanceof ClassSource) {
+                       return Optional.of(((ClassSource) 
testSource).getJavaClass().getName());
+               }
+               if (testSource instanceof MethodSource) {
+                       return Optional.of(((MethodSource) 
testSource).getClassName());
+               }
+               return Optional.empty();
+       }
+
+       private Optional<String> getMethodName(TestIdentifier testIdentifier) {
+               TestSource testSource = testIdentifier.getSource().orElse(null);
+               if (testSource instanceof MethodSource) {
+                       return Optional.of(((MethodSource) 
testSource).getMethodName());
+               }
+               return Optional.empty();
+       }
+
+       private String parentDisplayName(TestIdentifier testIdentifier) {
+               // @formatter:off
+               return testPlan
+                       .flatMap(plan -> plan.getParent(testIdentifier))
+                       .map(TestIdentifier::getDisplayName)
+                       .orElseGet(testIdentifier::getUniqueId);
+               // @formatter:on
+       }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/4bf43aab/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/TestPlanScannerFilter.java
----------------------------------------------------------------------
diff --git 
a/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/TestPlanScannerFilter.java
 
b/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/TestPlanScannerFilter.java
new file mode 100644
index 0000000..fd1796d
--- /dev/null
+++ 
b/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/TestPlanScannerFilter.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015-2017 the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.junit.platform.surefire.provider;
+
+import static 
org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
+import static 
org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
+
+import java.util.function.Predicate;
+
+import org.apache.maven.surefire.util.ScannerFilter;
+import org.junit.platform.engine.Filter;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.LauncherDiscoveryRequest;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+
+/**
+ * @since 1.0
+ */
+final class TestPlanScannerFilter implements ScannerFilter {
+
+       private static final Predicate<TestIdentifier> hasTests = 
testIdentifier -> testIdentifier.isTest()
+                       || testIdentifier.isContainer();
+
+       private final Launcher launcher;
+       private final Filter<?>[] includeAndExcludeFilters;
+
+       public TestPlanScannerFilter(Launcher launcher, Filter<?>[] 
includeAndExcludeFilters) {
+               this.launcher = launcher;
+               this.includeAndExcludeFilters = includeAndExcludeFilters;
+       }
+
+       @Override
+       @SuppressWarnings("rawtypes")
+       public boolean accept(Class testClass) {
+               LauncherDiscoveryRequest discoveryRequest = 
request().selectors(selectClass(testClass)).filters(
+                       includeAndExcludeFilters).build();
+               TestPlan testPlan = launcher.discover(discoveryRequest);
+               return testPlan.countTestIdentifiers(hasTests) > 0;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/4bf43aab/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/package-info.java
----------------------------------------------------------------------
diff --git 
a/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/package-info.java
 
b/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/package-info.java
new file mode 100644
index 0000000..29b0c3d
--- /dev/null
+++ 
b/surefire-providers/surefire-junit5/src/main/java/org/junit/platform/surefire/provider/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Maven Surefire provider for the JUnit Platform.
+ */
+
+package org.junit.platform.surefire.provider;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/4bf43aab/surefire-providers/surefire-junit5/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider
----------------------------------------------------------------------
diff --git 
a/surefire-providers/surefire-junit5/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider
 
b/surefire-providers/surefire-junit5/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider
new file mode 100644
index 0000000..bb76525
--- /dev/null
+++ 
b/surefire-providers/surefire-junit5/src/main/resources/META-INF/services/org.apache.maven.surefire.providerapi.SurefireProvider
@@ -0,0 +1 @@
+org.junit.platform.surefire.provider.JUnitPlatformProvider

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/4bf43aab/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/JUnitPlatformProviderTests.java
----------------------------------------------------------------------
diff --git 
a/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/JUnitPlatformProviderTests.java
 
b/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/JUnitPlatformProviderTests.java
new file mode 100644
index 0000000..798e471
--- /dev/null
+++ 
b/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/JUnitPlatformProviderTests.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2015-2017 the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.junit.platform.surefire.provider;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.maven.surefire.providerapi.ProviderParameters;
+import org.apache.maven.surefire.report.ReporterFactory;
+import org.apache.maven.surefire.report.RunListener;
+import org.apache.maven.surefire.util.RunOrderCalculator;
+import org.apache.maven.surefire.util.ScanResult;
+import org.apache.maven.surefire.util.TestsToRun;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.platform.commons.util.PreconditionViolationException;
+import org.junit.platform.launcher.Launcher;
+import org.junit.platform.launcher.TestPlan;
+import org.junit.platform.launcher.core.LauncherFactory;
+import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
+import org.junit.platform.launcher.listeners.TestExecutionSummary;
+
+/**
+ * Unit tests for {@link JUnitPlatformProvider}.
+ *
+ * @since 1.0
+ */
+class JUnitPlatformProviderTests {
+
+       @Test
+       void getSuitesReturnsScannedClasses() throws Exception {
+               ProviderParameters providerParameters = 
providerParametersMock(TestClass1.class, TestClass2.class);
+               JUnitPlatformProvider provider = new 
JUnitPlatformProvider(providerParameters);
+
+               assertThat(provider.getSuites()).containsOnly(TestClass1.class, 
TestClass2.class);
+       }
+
+       @Test
+       void invokeThrowsForWrongForkTestSet() throws Exception {
+               ProviderParameters providerParameters = 
providerParametersMock(Integer.class);
+               JUnitPlatformProvider provider = new 
JUnitPlatformProvider(providerParameters);
+
+               assertThrows(IllegalArgumentException.class, () -> 
provider.invoke("wrong forkTestSet"));
+       }
+
+       @Test
+       void allGivenTestsToRunAreInvoked() throws Exception {
+               Launcher launcher = LauncherFactory.create();
+               JUnitPlatformProvider provider = new 
JUnitPlatformProvider(providerParametersMock(), launcher);
+
+               TestPlanSummaryListener executionListener = new 
TestPlanSummaryListener();
+               launcher.registerTestExecutionListeners(executionListener);
+
+               TestsToRun testsToRun = newTestsToRun(TestClass1.class, 
TestClass2.class);
+               provider.invoke(testsToRun);
+
+               assertThat(executionListener.summaries).hasSize(2);
+               
TestClass1.verifyExecutionSummary(executionListener.summaries.get(0));
+               
TestClass2.verifyExecutionSummary(executionListener.summaries.get(1));
+       }
+
+       @Test
+       void singleTestClassIsInvoked() throws Exception {
+               Launcher launcher = LauncherFactory.create();
+               JUnitPlatformProvider provider = new 
JUnitPlatformProvider(providerParametersMock(), launcher);
+
+               TestPlanSummaryListener executionListener = new 
TestPlanSummaryListener();
+               launcher.registerTestExecutionListeners(executionListener);
+
+               provider.invoke(TestClass1.class);
+
+               assertThat(executionListener.summaries).hasSize(1);
+               
TestClass1.verifyExecutionSummary(executionListener.summaries.get(0));
+       }
+
+       @Test
+       void allDiscoveredTestsAreInvokedForNullArgument() throws Exception {
+               ProviderParameters providerParameters = 
providerParametersMock(TestClass1.class, TestClass2.class);
+               Launcher launcher = LauncherFactory.create();
+               JUnitPlatformProvider provider = new 
JUnitPlatformProvider(providerParameters, launcher);
+
+               TestPlanSummaryListener executionListener = new 
TestPlanSummaryListener();
+               launcher.registerTestExecutionListeners(executionListener);
+
+               provider.invoke(null);
+
+               assertThat(executionListener.summaries).hasSize(2);
+               
TestClass1.verifyExecutionSummary(executionListener.summaries.get(0));
+               
TestClass2.verifyExecutionSummary(executionListener.summaries.get(1));
+       }
+
+       @Test
+       void bothGroupsAndIncludeTagsThrowsException() {
+               Map<String, String> properties = new HashMap<>();
+               properties.put(JUnitPlatformProvider.INCLUDE_GROUPS, "groupOne, 
groupTwo");
+               properties.put(JUnitPlatformProvider.INCLUDE_TAGS, "tagOne, 
tagTwo");
+               verifyPreconditionViolationException(properties);
+       }
+
+       @Test
+       void bothExcludedGroupsAndExcludeTagsThrowsException() {
+               Map<String, String> properties = new HashMap<>();
+               properties.put(JUnitPlatformProvider.EXCLUDE_GROUPS, "groupOne, 
groupTwo");
+               properties.put(JUnitPlatformProvider.EXCLUDE_TAGS, "tagOne, 
tagTwo");
+               verifyPreconditionViolationException(properties);
+       }
+
+       @Test
+       void onlyGroupsIsDeclared() throws Exception {
+               Map<String, String> properties = new HashMap<>();
+               properties.put(JUnitPlatformProvider.INCLUDE_GROUPS, "groupOne, 
groupTwo");
+
+               ProviderParameters providerParameters = 
providerParametersMock(TestClass1.class);
+               
when(providerParameters.getProviderProperties()).thenReturn(properties);
+
+               JUnitPlatformProvider provider = new 
JUnitPlatformProvider(providerParameters);
+
+               assertEquals(1, provider.includeAndExcludeFilters.length);
+       }
+
+       @Test
+       void onlyExcludeTagsIsDeclared() throws Exception {
+               Map<String, String> properties = new HashMap<>();
+               properties.put(JUnitPlatformProvider.EXCLUDE_TAGS, "tagOne, 
tagTwo");
+
+               ProviderParameters providerParameters = 
providerParametersMock(TestClass1.class);
+               
when(providerParameters.getProviderProperties()).thenReturn(properties);
+
+               JUnitPlatformProvider provider = new 
JUnitPlatformProvider(providerParameters);
+
+               assertEquals(1, provider.includeAndExcludeFilters.length);
+       }
+
+       @Test
+       void bothIncludeAndExcludeAreAllowed() throws Exception {
+               Map<String, String> properties = new HashMap<>();
+               properties.put(JUnitPlatformProvider.INCLUDE_TAGS, "tagOne, 
tagTwo");
+               properties.put(JUnitPlatformProvider.EXCLUDE_TAGS, "tagThree, 
tagFour");
+
+               ProviderParameters providerParameters = 
providerParametersMock(TestClass1.class);
+               
when(providerParameters.getProviderProperties()).thenReturn(properties);
+
+               JUnitPlatformProvider provider = new 
JUnitPlatformProvider(providerParameters);
+
+               assertEquals(2, provider.includeAndExcludeFilters.length);
+       }
+
+       @Test
+       void noFiltersAreCreatedIfNoPropertiesAreDeclared() throws Exception {
+               ProviderParameters providerParameters = 
providerParametersMock(TestClass1.class);
+
+               JUnitPlatformProvider provider = new 
JUnitPlatformProvider(providerParameters);
+
+               assertEquals(0, provider.includeAndExcludeFilters.length);
+       }
+
+       private void verifyPreconditionViolationException(Map<String, String> 
properties) {
+               ProviderParameters providerParameters = 
providerParametersMock(TestClass1.class);
+               
when(providerParameters.getProviderProperties()).thenReturn(properties);
+
+               Throwable throwable = 
assertThrows(PreconditionViolationException.class, () -> {
+                       new JUnitPlatformProvider(providerParameters);
+               });
+
+               
assertEquals(JUnitPlatformProvider.EXCEPTION_MESSAGE_BOTH_NOT_ALLOWED, 
throwable.getMessage());
+       }
+
+       private static ProviderParameters providerParametersMock(Class<?>... 
testClasses) {
+               TestsToRun testsToRun = newTestsToRun(testClasses);
+
+               ScanResult scanResult = mock(ScanResult.class);
+               when(scanResult.applyFilter(any(), 
any())).thenReturn(testsToRun);
+
+               RunOrderCalculator runOrderCalculator = 
mock(RunOrderCalculator.class);
+               
when(runOrderCalculator.orderTestClasses(any())).thenReturn(testsToRun);
+
+               ReporterFactory reporterFactory = mock(ReporterFactory.class);
+               RunListener runListener = mock(RunListener.class);
+               when(reporterFactory.createReporter()).thenReturn(runListener);
+
+               ProviderParameters providerParameters = 
mock(ProviderParameters.class);
+               when(providerParameters.getScanResult()).thenReturn(scanResult);
+               
when(providerParameters.getRunOrderCalculator()).thenReturn(runOrderCalculator);
+               
when(providerParameters.getReporterFactory()).thenReturn(reporterFactory);
+
+               return providerParameters;
+       }
+
+       private static TestsToRun newTestsToRun(Class<?>... testClasses) {
+               List<Class<?>> classesList = Arrays.asList(testClasses);
+               return new TestsToRun(new LinkedHashSet<>(classesList));
+       }
+
+       private class TestPlanSummaryListener extends SummaryGeneratingListener 
{
+
+               final List<TestExecutionSummary> summaries = new ArrayList<>();
+
+               @Override
+               public void testPlanExecutionFinished(TestPlan testPlan) {
+                       super.testPlanExecutionFinished(testPlan);
+                       summaries.add(getSummary());
+               }
+       }
+
+       private static class TestClass1 {
+
+               @Test
+               void test1() {
+               }
+
+               @Test
+               void test2() {
+               }
+
+               @Disabled
+               @Test
+               void test3() {
+               }
+
+               @Test
+               void test4() {
+                       throw new RuntimeException();
+               }
+
+               static void verifyExecutionSummary(TestExecutionSummary 
summary) {
+                       assertEquals(4, summary.getTestsFoundCount());
+                       assertEquals(3, summary.getTestsStartedCount());
+                       assertEquals(2, summary.getTestsSucceededCount());
+                       assertEquals(1, summary.getTestsSkippedCount());
+                       assertEquals(0, summary.getTestsAbortedCount());
+                       assertEquals(1, summary.getTestsFailedCount());
+               }
+       }
+
+       private static class TestClass2 {
+
+               @Test
+               void test1() {
+               }
+
+               @Test
+               void test2() {
+                       throw new RuntimeException();
+               }
+
+               @Test
+               void test3() {
+                       assumeTrue(false);
+               }
+
+               static void verifyExecutionSummary(TestExecutionSummary 
summary) {
+                       assertEquals(3, summary.getTestsFoundCount());
+                       assertEquals(3, summary.getTestsStartedCount());
+                       assertEquals(1, summary.getTestsSucceededCount());
+                       assertEquals(0, summary.getTestsSkippedCount());
+                       assertEquals(1, summary.getTestsAbortedCount());
+                       assertEquals(1, summary.getTestsFailedCount());
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/4bf43aab/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/RunListenerAdapterTests.java
----------------------------------------------------------------------
diff --git 
a/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/RunListenerAdapterTests.java
 
b/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/RunListenerAdapterTests.java
new file mode 100644
index 0000000..c343ff6
--- /dev/null
+++ 
b/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/RunListenerAdapterTests.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2015-2017 the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.junit.platform.surefire.provider;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.Optional;
+
+import org.apache.maven.surefire.report.ReportEntry;
+import org.apache.maven.surefire.report.RunListener;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.engine.descriptor.ClassTestDescriptor;
+import org.junit.jupiter.engine.descriptor.MethodTestDescriptor;
+import org.junit.platform.engine.TestDescriptor;
+import org.junit.platform.engine.TestExecutionResult;
+import org.junit.platform.engine.UniqueId;
+import org.junit.platform.engine.support.descriptor.EngineDescriptor;
+import org.junit.platform.launcher.TestIdentifier;
+import org.junit.platform.launcher.TestPlan;
+import org.mockito.ArgumentCaptor;
+
+/**
+ * Unit tests for {@link RunListenerAdapter}.
+ *
+ * @since 1.0
+ */
+class RunListenerAdapterTests {
+
+       private RunListener listener;
+       private RunListenerAdapter adapter;
+
+       @BeforeEach
+       public void setUp() {
+               listener = mock(RunListener.class);
+               adapter = new RunListenerAdapter(listener);
+       }
+
+       @Test
+       void notifiedWithCorrectNamesWhenMethodExecutionStarted() throws 
Exception {
+               ArgumentCaptor<ReportEntry> entryCaptor = 
ArgumentCaptor.forClass(ReportEntry.class);
+
+               adapter.executionStarted(newMethodIdentifier());
+               verify(listener).testStarting(entryCaptor.capture());
+
+               ReportEntry entry = entryCaptor.getValue();
+               assertEquals(MY_TEST_METHOD_NAME + "()", entry.getName());
+               assertEquals(MyTestClass.class.getName(), 
entry.getSourceName());
+               assertNotNull(entry.getStackTraceWriter());
+       }
+
+       @Test
+       void notNotifiedWhenClassExecutionStarted() throws Exception {
+               adapter.executionStarted(newClassIdentifier());
+               verify(listener, never()).testStarting(any());
+       }
+
+       @Test
+       void notNotifiedWhenEngineExecutionStarted() throws Exception {
+               adapter.executionStarted(newEngineIdentifier());
+               verify(listener, never()).testStarting(any());
+       }
+
+       @Test
+       void notifiedWhenMethodExecutionSkipped() throws Exception {
+               adapter.executionSkipped(newMethodIdentifier(), "test");
+               verify(listener).testSkipped(any());
+       }
+
+       @Test
+       void notifiedWithCorrectNamesWhenClassExecutionSkipped() throws 
Exception {
+               ArgumentCaptor<ReportEntry> entryCaptor = 
ArgumentCaptor.forClass(ReportEntry.class);
+
+               adapter.executionSkipped(newClassIdentifier(), "test");
+               verify(listener).testSkipped(entryCaptor.capture());
+
+               ReportEntry entry = entryCaptor.getValue();
+               
assertTrue(MyTestClass.class.getTypeName().contains(entry.getName()));
+               assertEquals(MyTestClass.class.getName(), 
entry.getSourceName());
+       }
+
+       @Test
+       void notifiedWhenEngineExecutionSkipped() throws Exception {
+               adapter.executionSkipped(newEngineIdentifier(), "test");
+               verify(listener).testSkipped(any());
+       }
+
+       @Test
+       void notifiedWhenMethodExecutionAborted() throws Exception {
+               adapter.executionFinished(newMethodIdentifier(), 
TestExecutionResult.aborted(null));
+               verify(listener).testAssumptionFailure(any());
+       }
+
+       @Test
+       void notifiedWhenClassExecutionAborted() throws Exception {
+               adapter.executionFinished(newClassIdentifier(), 
TestExecutionResult.aborted(null));
+               verify(listener).testAssumptionFailure(any());
+       }
+
+       @Test
+       void notifiedWhenMethodExecutionFailed() throws Exception {
+               adapter.executionFinished(newMethodIdentifier(), 
TestExecutionResult.failed(new RuntimeException()));
+               verify(listener).testFailed(any());
+       }
+
+       @Test
+       void notifiedWithCorrectNamesWhenClassExecutionFailed() throws 
Exception {
+               ArgumentCaptor<ReportEntry> entryCaptor = 
ArgumentCaptor.forClass(ReportEntry.class);
+
+               adapter.executionFinished(newClassIdentifier(), 
TestExecutionResult.failed(new RuntimeException()));
+               verify(listener).testFailed(entryCaptor.capture());
+
+               ReportEntry entry = entryCaptor.getValue();
+               assertEquals(MyTestClass.class.getName(), 
entry.getSourceName());
+               assertNotNull(entry.getStackTraceWriter());
+       }
+
+       @Test
+       void notifiedWhenMethodExecutionSucceeded() throws Exception {
+               adapter.executionFinished(newMethodIdentifier(), 
TestExecutionResult.successful());
+               verify(listener).testSucceeded(any());
+       }
+
+       @Test
+       void notNotifiedWhenClassExecutionSucceeded() throws Exception {
+               adapter.executionFinished(newClassIdentifier(), 
TestExecutionResult.successful());
+               verify(listener, never()).testSucceeded(any());
+       }
+
+       @Test
+       void notifiedWithParentDisplayNameWhenTestClassUnknown() throws 
Exception {
+               // Set up a test plan
+               TestPlan plan = TestPlan.from(Collections.singletonList(new 
EngineDescriptor(newId(), "Luke's Plan")));
+               adapter.testPlanExecutionStarted(plan);
+
+               // Use the test plan to set up child with parent.
+               final String parentDisplay = "I am your father";
+               TestIdentifier child = newSourcelessIdentifierWithParent(plan, 
parentDisplay);
+               adapter.executionStarted(child);
+
+               // Check that the adapter has informed Surefire that the test 
has been invoked,
+               // with the parent name as source (since the test case itself 
had no source).
+               ArgumentCaptor<ReportEntry> entryCaptor = 
ArgumentCaptor.forClass(ReportEntry.class);
+               verify(listener).testStarting(entryCaptor.capture());
+               assertEquals(parentDisplay, 
entryCaptor.getValue().getSourceName());
+       }
+
+       private static TestIdentifier newMethodIdentifier() throws Exception {
+               TestDescriptor testDescriptor = new 
MethodTestDescriptor(newId(), MyTestClass.class,
+                       
MyTestClass.class.getDeclaredMethod(MY_TEST_METHOD_NAME));
+               return TestIdentifier.from(testDescriptor);
+       }
+
+       private static TestIdentifier newClassIdentifier() {
+               TestDescriptor testDescriptor = new 
ClassTestDescriptor(newId(), MyTestClass.class);
+               return TestIdentifier.from(testDescriptor);
+       }
+
+       private static TestIdentifier 
newSourcelessIdentifierWithParent(TestPlan testPlan, String parentDisplay) {
+               // A parent test identifier with a name.
+               TestDescriptor parent = mock(TestDescriptor.class);
+               when(parent.getUniqueId()).thenReturn(newId());
+               when(parent.getDisplayName()).thenReturn(parentDisplay);
+               TestIdentifier parentId = TestIdentifier.from(parent);
+
+               // The (child) test case that is to be executed as part of a 
test plan.
+               TestDescriptor child = mock(TestDescriptor.class);
+               when(child.getUniqueId()).thenReturn(newId());
+               when(child.isTest()).thenReturn(true);
+
+               // Ensure the child source is null yet that there is a parent 
-- the special case to be tested.
+               when(child.getSource()).thenReturn(Optional.empty());
+               when(child.getParent()).thenReturn(Optional.of(parent));
+               TestIdentifier childId = TestIdentifier.from(child);
+
+               testPlan.add(childId);
+               testPlan.add(parentId);
+
+               return childId;
+       }
+
+       private static TestIdentifier newEngineIdentifier() {
+               TestDescriptor testDescriptor = new EngineDescriptor(newId(), 
"engine");
+               return TestIdentifier.from(testDescriptor);
+       }
+
+       private static UniqueId newId() {
+               return UniqueId.forEngine("engine");
+       }
+
+       private static final String MY_TEST_METHOD_NAME = "myTestMethod";
+       private static class MyTestClass {
+               @Test
+               void myTestMethod() {
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/4bf43aab/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/SurefireProviderTestSuite.java
----------------------------------------------------------------------
diff --git 
a/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/SurefireProviderTestSuite.java
 
b/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/SurefireProviderTestSuite.java
new file mode 100644
index 0000000..3a52590
--- /dev/null
+++ 
b/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/SurefireProviderTestSuite.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015-2017 the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.junit.platform.surefire.provider;
+
+import org.junit.platform.runner.IncludeClassNamePatterns;
+import org.junit.platform.runner.IncludeEngines;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.platform.runner.SelectPackages;
+import org.junit.runner.RunWith;
+
+/**
+ * Test suite for the JUnit Platform Surefire Provider.
+ *
+ * <h3>Logging Configuration</h3>
+ *
+ * <p>In order for our log4j2 configuration to be used in an IDE, you must
+ * set the following system property before running any tests &mdash; for
+ * example, in <em>Run Configurations</em> in Eclipse.
+ *
+ * <pre class="code">
+ * -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
+ * </pre>
+ *
+ * @since 1.0
+ */
+@RunWith(JUnitPlatform.class)
+@SelectPackages("org.junit.platform.surefire.provider")
+@IncludeClassNamePatterns(".*Tests?")
+@IncludeEngines("junit-jupiter")
+public class SurefireProviderTestSuite {
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/4bf43aab/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/TestPlanScannerFilterTests.java
----------------------------------------------------------------------
diff --git 
a/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/TestPlanScannerFilterTests.java
 
b/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/TestPlanScannerFilterTests.java
new file mode 100644
index 0000000..bd48d66
--- /dev/null
+++ 
b/surefire-providers/surefire-junit5/src/test/java/org/junit/platform/surefire/provider/TestPlanScannerFilterTests.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2015-2017 the original author or authors.
+ *
+ * Licensed 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.
+ */
+
+package org.junit.platform.surefire.provider;
+
+import static java.util.Collections.emptyList;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.DynamicTest;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestFactory;
+import org.junit.platform.engine.Filter;
+import org.junit.platform.launcher.core.LauncherFactory;
+
+/**
+ * Unit tests for {@link TestPlanScannerFilter}.
+ *
+ * @since 1.0
+ */
+public class TestPlanScannerFilterTests {
+
+       @Test
+       void emptyClassAccepted() {
+               assertTrue(newFilter().accept(EmptyClass.class), "accepts empty 
class because it is a container");
+       }
+
+       @Test
+       void classWithNoTestMethodsIsAccepted() {
+               assertTrue(newFilter().accept(ClassWithMethods.class),
+                       "accepts class with no @Test methods because it is a 
container");
+       }
+
+       @Test
+       void classWithTestMethodsIsAccepted() {
+               assertTrue(newFilter().accept(ClassWithTestMethods.class));
+       }
+
+       @Test
+       void classWithNestedTestClassIsAccepted() {
+               assertTrue(newFilter().accept(ClassWithNestedTestClass.class));
+       }
+
+       @Test
+       void classWithDeeplyNestedTestClassIsAccepted() {
+               
assertTrue(newFilter().accept(ClassWithDeeplyNestedTestClass.class));
+       }
+
+       @Test
+       void classWithTestFactoryIsAccepted() {
+               assertTrue(newFilter().accept(ClassWithTestFactory.class));
+       }
+
+       @Test
+       void classWithNestedTestFactoryIsAccepted() {
+               
assertTrue(newFilter().accept(ClassWithNestedTestFactory.class));
+       }
+
+       private TestPlanScannerFilter newFilter() {
+               return new TestPlanScannerFilter(LauncherFactory.create(), new 
Filter<?>[0]);
+       }
+
+       private static class EmptyClass {
+       }
+
+       @SuppressWarnings("unused")
+       private static class ClassWithMethods {
+
+               void method1() {
+               }
+
+               void method2() {
+               }
+       }
+
+       private static class ClassWithTestMethods {
+
+               @Test
+               void test1() {
+               }
+
+               @Test
+               public void test2() {
+               }
+       }
+
+       private static class ClassWithNestedTestClass {
+
+               @SuppressWarnings("unused")
+               void method() {
+               }
+
+               @Nested
+               class TestClass {
+
+                       @Test
+                       void test1() {
+                       }
+               }
+       }
+
+       private static class ClassWithDeeplyNestedTestClass {
+
+               @Nested
+               class Level1 {
+
+                       @Nested
+                       class Level2 {
+
+                               @Nested
+                               class TestClass {
+
+                                       @Test
+                                       void test1() {
+                                       }
+                               }
+                       }
+               }
+       }
+
+       private static class ClassWithTestFactory {
+
+               @TestFactory
+               Stream<DynamicTest> tests() {
+                       return Stream.empty();
+               }
+       }
+
+       private static class ClassWithNestedTestFactory {
+
+               @Nested
+               class TestClass {
+
+                       @TestFactory
+                       List<DynamicTest> tests() {
+                               return emptyList();
+                       }
+               }
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/4bf43aab/surefire-providers/surefire-junit5/src/test/resources/log4j2-test.xml
----------------------------------------------------------------------
diff --git 
a/surefire-providers/surefire-junit5/src/test/resources/log4j2-test.xml 
b/surefire-providers/surefire-junit5/src/test/resources/log4j2-test.xml
new file mode 100644
index 0000000..27875d9
--- /dev/null
+++ b/surefire-providers/surefire-junit5/src/test/resources/log4j2-test.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="WARN">
+       <Appenders>
+               <Console name="Console" target="SYSTEM_OUT">
+                       <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level 
%logger{36} - %msg%n" />
+               </Console>
+       </Appenders>
+       <Loggers>
+               <Logger name="org.junit" level="warn" />
+               <Logger name="org.junit.platform.surefire" level="error" />
+               <Root level="error">
+                       <AppenderRef ref="Console" />
+               </Root>
+       </Loggers>
+</Configuration>
\ No newline at end of file

Reply via email to