org.junit.platform.launcher.TagFilter Maven / Gradle / Ivy
/*
* Copyright 2015-2019 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 v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.platform.launcher;
import static java.util.Arrays.asList;
import static org.apiguardian.api.API.Status.STABLE;
import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList;
import java.util.List;
import java.util.Set;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.apiguardian.api.API;
import org.junit.platform.commons.PreconditionViolationException;
import org.junit.platform.commons.util.Preconditions;
import org.junit.platform.engine.FilterResult;
import org.junit.platform.engine.TestTag;
import org.junit.platform.launcher.tagexpression.TagExpression;
/**
* Factory methods for creating {@link PostDiscoveryFilter PostDiscoveryFilters}
* based on included and excluded tags or tag expressions.
*
* Tag expressions are boolean expressions with the following allowed
* operators: {@code !} (not), {@code &} (and), and {@code |} (or). Parentheses
* can be used to adjust for operator precedence. Please refer to the
* JUnit 5 User Guide
* for usage examples.
*
*
Please note that a tag name is a valid tag expression. Thus, wherever a tag
* expression can be used, a single tag name can also be used.
*
* @since 1.0
* @see #includeTags(String...)
* @see #excludeTags(String...)
* @see TestTag
*/
@API(status = STABLE, since = "1.0")
public final class TagFilter {
private TagFilter() {
/* no-op */
}
/**
* Create an include filter based on the supplied tag expressions.
*
*
Containers and tests will only be executed if their tags match at
* least one of the supplied included tag expressions.
*
* @param tagExpressions the included tag expressions; never {@code null} or
* empty
* @throws PreconditionViolationException if the supplied tag expressions
* array is {@code null} or empty, or if any individual tag expression is
* not syntactically valid
* @see #includeTags(List)
* @see TestTag#isValid(String)
*/
public static PostDiscoveryFilter includeTags(String... tagExpressions) throws PreconditionViolationException {
Preconditions.notNull(tagExpressions, "array of tag expressions must not be null");
return includeTags(asList(tagExpressions));
}
/**
* Create an include filter based on the supplied tag expressions.
*
*
Containers and tests will only be executed if their tags match at
* least one of the supplied included tag expressions.
*
* @param tagExpressions the included tag expressions; never {@code null} or
* empty
* @throws PreconditionViolationException if the supplied tag expressions
* array is {@code null} or empty, or if any individual tag expression is
* not syntactically valid
* @see #includeTags(String...)
* @see TestTag#isValid(String)
*/
public static PostDiscoveryFilter includeTags(List tagExpressions) throws PreconditionViolationException {
return includeMatching(tagExpressions, Stream::anyMatch);
}
/**
* Create an exclude filter based on the supplied tag expressions.
*
* Containers and tests will only be executed if their tags do
* not match any of the supplied excluded tag expressions.
*
* @param tagExpressions the excluded tag expressions; never {@code null} or
* empty
* @throws PreconditionViolationException if the supplied tag expressions
* array is {@code null} or empty, or if any individual tag expression is
* not syntactically valid
* @see #excludeTags(List)
* @see TestTag#isValid(String)
*/
public static PostDiscoveryFilter excludeTags(String... tagExpressions) throws PreconditionViolationException {
Preconditions.notNull(tagExpressions, "array of tag expressions must not be null");
return excludeTags(asList(tagExpressions));
}
/**
* Create an exclude filter based on the supplied tag expressions.
*
*
Containers and tests will only be executed if their tags do
* not match any of the supplied excluded tag expressions.
*
* @param tagExpressions the excluded tag expressions; never {@code null} or
* empty
* @throws PreconditionViolationException if the supplied tag expressions
* array is {@code null} or empty, or if any individual tag expression is
* not syntactically valid
* @see #excludeTags(String...)
* @see TestTag#isValid(String)
*/
public static PostDiscoveryFilter excludeTags(List tagExpressions) throws PreconditionViolationException {
return includeMatching(tagExpressions, Stream::noneMatch);
}
private static PostDiscoveryFilter includeMatching(List tagExpressions,
BiPredicate, Predicate> matcher) {
Preconditions.notEmpty(tagExpressions, "list of tag expressions must not be null or empty");
List parsedTagExpressions = parseAll(tagExpressions);
return descriptor -> {
Set tags = descriptor.getTags();
return FilterResult.includedIf(
matcher.test(parsedTagExpressions.stream(), expression -> expression.evaluate(tags)));
};
}
private static List parseAll(List tagExpressions) {
return tagExpressions.stream().map(TagFilter::parse).collect(toUnmodifiableList());
}
private static TagExpression parse(String tagExpression) {
return TagExpression.parseFrom(tagExpression).tagExpressionOrThrow(
message -> new PreconditionViolationException(
"Unable to parse tag expression \"" + tagExpression + "\": " + message));
}
}