Создать условие выполнения ExcludeTagsCondition
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.platform.commons.util.AnnotationUtils;
public class ExcludeTagsCondition implements ExecutionCondition {
private static final ConditionEvaluationResult ENABLED_IF_EXCLUDE_TAG_IS_INVALID =
ConditionEvaluationResult.enabled(
"@ExcludeTags does not have a valid tag to exclude, all tests will be run");
private static Set<String> tagsThatMustBeIncluded = new HashSet<>();
public static void setMustIncludeTags(final Set<String> tagsThatMustBeIncluded) {
ExcludeTagsCondition.tagsThatMustBeIncluded = new HashSet<>(tagsThatMustBeIncluded);
}
@Override
public ConditionEvaluationResult evaluateExecutionCondition(
ExtensionContext context) {
final AnnotatedElement element = context
.getElement()
.orElseThrow(IllegalStateException::new);
final Optional<Set<String>> tagsToExclude = AnnotationUtils.findAnnotation(
context.getRequiredTestClass(),
ExcludeTags.class
)
.map(a ->
Arrays.asList(a.value())
.stream()
.filter(t -> !tagsThatMustBeIncluded.contains(t))
.collect(Collectors.toSet())
);
if (!tagsToExclude.isPresent() || tagsToExclude.get().stream()
.allMatch(s -> (s == null) || s.trim().isEmpty())) {
return ENABLED_IF_EXCLUDE_TAG_IS_INVALID;
}
final Optional<String> tag = AnnotationUtils.findAnnotation(element, Tag.class)
.map(Tag::value);
if (tagsToExclude.get().contains(tag.map(String::trim).orElse(""))) {
return ConditionEvaluationResult
.disabled(String.format(
"test method \"%s\" has tag \"%s\" which is on the @ExcludeTags list \"[%s]\", test will be skipped",
(element instanceof Method) ? ((Method) element).getName()
: element.getClass().getSimpleName(),
tag.get(),
tagsToExclude.get().stream().collect(Collectors.joining(","))
));
}
return ConditionEvaluationResult.enabled(
String.format(
"test method \"%s\" has tag \"%s\" which is not on the @ExcludeTags list \"[%s]\", test will be run",
(element instanceof Method) ? ((Method) element).getName()
: element.getClass().getSimpleName(),
tag.orElse("<no tag present>"),
tagsToExclude.get().stream().collect(Collectors.joining(","))
));
}
}
Создать аннотацию @ExcludeTags
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.junit.jupiter.api.extension.ExtendWith;
@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
@ExtendWith(ExcludeTagsCondition.class)
public @interface ExcludeTags {
String[] value();
}
В вашем тесте
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@ExcludeTags({"foo", "bar"})
@SpringBootTest
class AppTest {
@Test
@Tag("foo")
void test1() {
System.out.println("test1");
}
@Test
@Tag("bar")
void test2() {
System.out.println("test2");
}
@Test
@Tag("baz")
void test3() {
System.out.println("test3");
}
}
При запуске теста вы должны увидеть следующий результат:
test method "test1" has tag "foo" which is on the @ExcludeTags list "[bar,foo]", test will be skipped
test method "test2" has tag "bar" which is on the @ExcludeTags list "[bar,foo]", test will be skipped
test3
И ваш тестовый исполнитель должен показать 1 прохождение теста и 2 пропущенных.
![enter image description here](https://i.stack.imgur.com/KoA8E.png)
Now for your test suite:
Create an annotation @MustIncludeTags
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Target({ TYPE, ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface MustIncludeTags {
String[] value();
}
Теперь настройте свой набор тестов следующим образом:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Optional;
import java.util.stream.Collectors;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.runner.RunWith;
@RunWith(JUnitPlatform.class)
@SelectClasses({MyTestSuite.SetupTests.class, AppTest.class})
@MustIncludeTags({"foo", "bar"})
public class MyTestSuite {
public static class SetupTests {
@BeforeAll
public static void beforeClass() {
ExcludeTagsCondition.setMustIncludeTags(
Optional.ofNullable(MyTestSuite.class.getAnnotation(MustIncludeTags.class))
.map(MustIncludeTags::value)
.map(Arrays::asList)
.orElse(new ArrayList<>())
.stream()
.collect(Collectors.toSet())
);
}
@Disabled
@Test
void testDummy() {
// this test needs to be present for the beforeAll to run
}
}
}
Когда вы запускаете свой набор тестов с @MustIncludeTags
, @ExcludedTags
переопределяются.
Как видно из следующего выполнения теста :
введите описание изображения здесь