From 8d0c8a44fa4f1fb8e1ce4ddc256673f031cfaa48 Mon Sep 17 00:00:00 2001 From: Stuart Douglas Date: Mon, 22 May 2023 17:14:23 +1000 Subject: [PATCH] Support tag expressions Fixes #33515 --- .../dev/testing/JunitTestRunner.java | 74 +------------------ .../deployment/dev/testing/TestConfig.java | 10 ++- .../dev/testing/TestTracingProcessor.java | 12 +-- 3 files changed, 17 insertions(+), 79 deletions(-) diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/JunitTestRunner.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/JunitTestRunner.java index c237568887185..ee468ee0a929e 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/JunitTestRunner.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/JunitTestRunner.java @@ -2,8 +2,6 @@ import java.io.IOException; import java.io.InputStream; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.file.Files; import java.nio.file.Path; @@ -37,8 +35,6 @@ import org.jboss.logging.Logger; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Tags; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestTemplate; @@ -57,6 +53,7 @@ import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.PostDiscoveryFilter; +import org.junit.platform.launcher.TagFilter; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; @@ -163,9 +160,9 @@ public FilterResult apply(TestDescriptor testDescriptor) { launchBuilder.filters(testClassUsages.getTestsToRun(classScanResult.getChangedClassNames(), testState)); } if (!includeTags.isEmpty()) { - launchBuilder.filters(new TagFilter(false, includeTags)); + launchBuilder.filters(TagFilter.includeTags(new ArrayList<>(includeTags))); } else if (!excludeTags.isEmpty()) { - launchBuilder.filters(new TagFilter(true, excludeTags)); + launchBuilder.filters(TagFilter.excludeTags(new ArrayList<>(excludeTags))); } if (include != null) { launchBuilder.filters(new RegexFilter(false, include)); @@ -852,71 +849,6 @@ public Builder setFailingTestsOnly(boolean failingTestsOnly) { } } - private static class TagFilter implements PostDiscoveryFilter { - - final boolean exclude; - final Set tags; - - private TagFilter(boolean exclude, Set tags) { - this.exclude = exclude; - this.tags = tags; - } - - @Override - public FilterResult apply(TestDescriptor testDescriptor) { - if (testDescriptor.getSource().isPresent()) { - if (testDescriptor.getSource().get() instanceof MethodSource) { - MethodSource methodSource = (MethodSource) testDescriptor.getSource().get(); - Method m = methodSource.getJavaMethod(); - FilterResult res = filterTags(m); - if (res != null) { - return res; - } - res = filterTags(methodSource.getJavaClass()); - if (res != null) { - return res; - } - return FilterResult.includedIf(exclude); - } - } - return FilterResult.included("not a method"); - } - - public FilterResult filterTags(AnnotatedElement clz) { - List all = new ArrayList<>(); - gatherTags(clz, all); - if (all.isEmpty()) - return null; - for (Tag i : all) { - if (tags.contains(i.value())) { - return FilterResult.includedIf(!exclude); - } - } - return FilterResult.includedIf(exclude); - } - - private void gatherTags(AnnotatedElement clz, List all) { - Tag tag = clz.getAnnotation(Tag.class); - Tags tagsAnn = clz.getAnnotation(Tags.class); - if (tag != null) { - all.add(tag); - } else if (tagsAnn != null) { - all.addAll(List.of(tagsAnn.value())); - } - if (clz instanceof Class) { - if (((Class) clz).isAnnotation()) { - //only scan meta annotations one level deep - return; - } - } - - //meta annotations can also provide tags - for (var a : clz.getAnnotations()) { - gatherTags(a.annotationType(), all); - } - } - } - private static class RegexFilter implements PostDiscoveryFilter { final boolean exclude; diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestConfig.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestConfig.java index 57d0a0aece9cb..1874eeaaf894f 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestConfig.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestConfig.java @@ -41,7 +41,9 @@ public class TestConfig { public boolean displayTestOutput; /** - * Tags that should be included for continuous testing. + * Tags that should be included for continuous testing. This supports JUnit Tag Expressions. + * + * @see JUnit Tag Expressions */ @ConfigItem public Optional> includeTags; @@ -51,7 +53,11 @@ public class TestConfig { * * This is ignored if include-tags has been set. * - * Defaults to 'slow' + * Defaults to 'slow'. + * + * This supports JUnit Tag Expressions. + * + * @see JUnit Tag Expressions */ @ConfigItem(defaultValue = "slow") public Optional> excludeTags; diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestTracingProcessor.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestTracingProcessor.java index 27f21d8104ab8..d72622e78dcc4 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestTracingProcessor.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/testing/TestTracingProcessor.java @@ -198,7 +198,7 @@ ConsoleCommandBuildItem testConsoleCommand(CombinedIndexBuildItem indexBuildItem } @GroupCommandDefinition(name = "test", description = "Test Commands", groupCommands = { TagsCommand.class, - PatternCommand.class }) + PatternCommand.class }, generateHelp = true) public static class TestCommand implements Command { @Override @@ -208,7 +208,7 @@ public CommandResult execute(CommandInvocation commandInvocation) throws Command } @GroupCommandDefinition(name = "tags", description = "Tag Commands", groupCommands = { IncludeTagsCommand.class, - ExcludeTagsCommand.class }) + ExcludeTagsCommand.class }, generateHelp = true) public static class TagsCommand implements Command { @Override @@ -217,7 +217,7 @@ public CommandResult execute(CommandInvocation commandInvocation) throws Command } } - @CommandDefinition(name = "include", description = "Sets the current included tags") + @CommandDefinition(name = "include", description = "Sets the current included tags, this supports JUnit tag expressions.") public static class IncludeTagsCommand extends TestSelectionCommand { @Arguments(completer = TagCompleter.class) @@ -243,7 +243,7 @@ protected void configure(TestSupport testSupport) { } } - @CommandDefinition(name = "exclude", description = "Sets the current excluded tags") + @CommandDefinition(name = "exclude", description = "Sets the current excluded tags, this supports JUnit tag expressions.") public static class ExcludeTagsCommand extends TestSelectionCommand { @Arguments(completer = TagCompleter.class) @@ -271,7 +271,7 @@ protected void configure(TestSupport testSupport) { @GroupCommandDefinition(name = "pattern", description = "Include/Exclude pattern Commands", groupCommands = { IncludePatternCommand.class, - ExcludePatternCommand.class }) + ExcludePatternCommand.class }, generateHelp = true) public static class PatternCommand implements Command { @Override @@ -302,7 +302,7 @@ protected void configure(TestSupport testSupport) { } } - @CommandDefinition(name = "exclude", description = "Sets the current excluded tags") + @CommandDefinition(name = "exclude", description = "Sets the current exclude pattern") public static class ExcludePatternCommand extends TestSelectionCommand { @Argument(completer = TagCompleter.class)