Repository: maven-surefire Updated Branches: refs/heads/3.0-rc1 b1f190427 -> c9a1f973e
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/73e09a8b Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/73e09a8b Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/73e09a8b Branch: refs/heads/3.0-rc1 Commit: 73e09a8b2b245e76e072c1809e7fa50be02e95b6 Parents: b1f1904 Author: Benedikt Ritter <brit...@apache.org> Authored: Mon Feb 6 14:02:48 2017 +0100 Committer: Benedikt Ritter <brit...@apache.org> Committed: Mon Feb 6 14:02:48 2017 +0100 ---------------------------------------------------------------------- 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/73e09a8b/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_ +_<<http://www.apache.org/licenses/>>_ + +### 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/73e09a8b/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/73e09a8b/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/73e09a8b/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/73e09a8b/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/73e09a8b/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/73e09a8b/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/73e09a8b/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/73e09a8b/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 — 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/73e09a8b/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/73e09a8b/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