/* * 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; } }