/* * Copyright 2015-2017 the original author or authors. * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution and is available at * * http://www.eclipse.org/legal/epl-v10.html */ package org.junit.platform.launcher.core; import static org.junit.platform.commons.meta.API.Usage.Experimental; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.junit.platform.commons.meta.API; import org.junit.platform.commons.util.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.DiscoveryFilter; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.Filter; import org.junit.platform.launcher.EngineFilter; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.PostDiscoveryFilter; /** * The {@code LauncherDiscoveryRequestBuilder} provides a light-weight DSL for * generating a {@link LauncherDiscoveryRequest}. * * <h4>Example</h4> * * <pre class="code"> * import static org.junit.platform.engine.discovery.DiscoverySelectors.*; * import static org.junit.platform.engine.discovery.ClassNameFilter.*; * import static org.junit.platform.launcher.EngineFilter.*; * import static org.junit.platform.launcher.TagFilter.*; * * // ... * * LauncherDiscoveryRequestBuilder.request() * .selectors( * selectPackage("org.example.user"), * selectClass("org.example.payment.PaymentTests"), * selectClass(ShippingTests.class), * selectMethod("org.example.order.OrderTests#test1"), * selectMethod("org.example.order.OrderTests#test2()"), * selectMethod("org.example.order.OrderTests#test3(java.lang.String)"), * selectMethod("org.example.order.OrderTests", "test4"), * selectMethod(OrderTests.class, "test5"), * selectMethod(OrderTests.class, testMethod), * selectClasspathRoots(Collections.singleton(new File("/my/local/path1"))), * selectUniqueId("unique-id-1"), * selectUniqueId("unique-id-2") * ) * .filters( * includeEngines("junit-jupiter", "spek"), * // excludeEngines("junit-vintage"), * includeTags("fast"), * // excludeTags("slow"), * includeClassNamePatterns(".*Test[s]?") * // includeClassNamePatterns("org\.example\.tests.*") * ) * .configurationParameter("key1", "value1") * .configurationParameters(configParameterMap) * .build(); * </pre> * * @since 1.0 * @see org.junit.platform.engine.discovery.DiscoverySelectors * @see org.junit.platform.engine.discovery.ClassNameFilter * @see org.junit.platform.launcher.EngineFilter * @see org.junit.platform.launcher.TagFilter */ @API(Experimental) public final class LauncherDiscoveryRequestBuilder { private List<DiscoverySelector> selectors = new LinkedList<>(); private List<EngineFilter> engineFilters = new LinkedList<>(); private List<DiscoveryFilter<?>> discoveryFilters = new LinkedList<>(); private List<PostDiscoveryFilter> postDiscoveryFilters = new LinkedList<>(); private Map<String, String> configurationParameters = new HashMap<>(); /** * Create a new {@code LauncherDiscoveryRequestBuilder}. * * @return a new builder */ public static LauncherDiscoveryRequestBuilder request() { return new LauncherDiscoveryRequestBuilder(); } /** * Add all of the supplied {@code selectors} to the request. * * @param selectors the {@code DiscoverySelectors} to add; never {@code null} * @return this builder for method chaining */ public LauncherDiscoveryRequestBuilder selectors(DiscoverySelector... selectors) { Preconditions.notNull(selectors, "selectors array must not be null"); selectors(Arrays.asList(selectors)); return this; } /** * Add all of the supplied {@code selectors} to the request. * * @param selectors the {@code DiscoverySelectors} to add; never {@code null} * @return this builder for method chaining */ public LauncherDiscoveryRequestBuilder selectors(List<? extends DiscoverySelector> selectors) { Preconditions.notNull(selectors, "selectors list must not be null"); Preconditions.containsNoNullElements(selectors, "individual selectors must not be null"); this.selectors.addAll(selectors); return this; } /** * Add all of the supplied {@code filters} to the request. * * <p>The {@code filters} are combined using AND semantics, i.e. all of them * have to include a resource for it to end up in the test plan. * * <p><strong>Warning</strong>: be cautious when registering multiple competing * {@link EngineFilter#includeEngines include} {@code EngineFilters} or multiple * competing {@link EngineFilter#excludeEngines exclude} {@code EngineFilters} * for the same discovery request since doing so will likely lead to * undesirable results (i.e., zero engines being active). * * @param filters the {@code Filter}s to add; never {@code null} * @return this builder for method chaining */ public LauncherDiscoveryRequestBuilder filters(Filter<?>... filters) { Preconditions.notNull(filters, "filters array must not be null"); Preconditions.containsNoNullElements(filters, "individual filters must not be null"); Arrays.stream(filters).forEach(this::storeFilter); return this; } /** * Add the supplied <em>configuration parameter</em> to the request. * * @param key the configuration parameter key under which to store the * value; never {@code null} or blank * @param value the value to store * @return this builder for method chaining */ public LauncherDiscoveryRequestBuilder configurationParameter(String key, String value) { Preconditions.notBlank(key, "configuration parameter key must not be null or blank"); this.configurationParameters.put(key, value); return this; } /** * Add all of the supplied configuration parameters to the request. * * @param configurationParameters the map of configuration parameters to add; * never {@code null} * @return this builder for method chaining * @see #configurationParameter(String, String) */ public LauncherDiscoveryRequestBuilder configurationParameters(Map<String, String> configurationParameters) { Preconditions.notNull(configurationParameters, "configuration parameters map must not be null"); configurationParameters.forEach(this::configurationParameter); return this; } private void storeFilter(Filter<?> filter) { if (filter instanceof EngineFilter) { this.engineFilters.add((EngineFilter) filter); } else if (filter instanceof PostDiscoveryFilter) { this.postDiscoveryFilters.add((PostDiscoveryFilter) filter); } else if (filter instanceof DiscoveryFilter<?>) { this.discoveryFilters.add((DiscoveryFilter<?>) filter); } else { throw new PreconditionViolationException( String.format("Filter [%s] must implement %s, %s, or %s.", filter, EngineFilter.class.getSimpleName(), PostDiscoveryFilter.class.getSimpleName(), DiscoveryFilter.class.getSimpleName())); } } /** * Build the {@link LauncherDiscoveryRequest} that has been configured via * this builder. */ public LauncherDiscoveryRequest build() { LauncherConfigurationParameters launcherConfigurationParameters = new LauncherConfigurationParameters( this.configurationParameters); return new DefaultDiscoveryRequest(this.selectors, this.engineFilters, this.discoveryFilters, this.postDiscoveryFilters, launcherConfigurationParameters); } }