Skip to content

Commit b14b09e

Browse files
committed
Handle Category from junit4
Signed-off-by: Olivier Lamy <[email protected]>
1 parent e6b952e commit b14b09e

File tree

3 files changed

+108
-5
lines changed

3 files changed

+108
-5
lines changed

maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
import static org.apache.maven.plugin.surefire.util.DependencyScanner.filter;
140140
import static org.apache.maven.surefire.api.booter.ProviderParameterNames.EXCLUDE_JUNIT5_ENGINES_PROP;
141141
import static org.apache.maven.surefire.api.booter.ProviderParameterNames.INCLUDE_JUNIT5_ENGINES_PROP;
142+
import static org.apache.maven.surefire.api.booter.ProviderParameterNames.JUNIT_VINTAGE_DETECTED;
142143
import static org.apache.maven.surefire.api.suite.RunResult.failure;
143144
import static org.apache.maven.surefire.api.suite.RunResult.noTestsRun;
144145
import static org.apache.maven.surefire.booter.Classpath.emptyClasspath;
@@ -3192,7 +3193,8 @@ public Set<Artifact> getProviderClasspath() throws MojoExecutionException {
31923193
String engineGroupId = "org.junit.vintage";
31933194
String engineArtifactId = "junit-vintage-engine";
31943195
String engineCoordinates = engineGroupId + ":" + engineArtifactId;
3195-
3196+
getProperties().setProperty(JUNIT_VINTAGE_DETECTED, "true");
3197+
// TODO exclude transitive deps (hamcrest etc...)
31963198
if (engineVersion != null) {
31973199
consoleLogger.debug("Test dependencies contain JUnit4. Resolving " + engineCoordinates + ":"
31983200
+ engineVersion);

surefire-api/src/main/java/org/apache/maven/surefire/api/booter/ProviderParameterNames.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,6 @@ public class ProviderParameterNames {
4949
public static final String ENABLE_OUT_ERR_ELEMENTS_PROP = "enableouterrelements";
5050

5151
public static final String ENABLE_PROPERTIES_ELEMENT_PROP = "enablepropertieselement";
52+
53+
public static final String JUNIT_VINTAGE_DETECTED = "junit.vintage.engine.detected";
5254
}

surefire-providers/surefire-junit-platform/src/main/java/org/apache/maven/surefire/junitplatform/JUnitPlatformProvider.java

Lines changed: 103 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
import java.io.IOException;
2222
import java.io.StringReader;
2323
import java.io.UncheckedIOException;
24+
import java.lang.annotation.Annotation;
25+
import java.lang.reflect.Method;
2426
import java.util.ArrayList;
27+
import java.util.Collections;
2528
import java.util.HashMap;
2629
import java.util.LinkedHashSet;
2730
import java.util.List;
@@ -31,6 +34,7 @@
3134
import java.util.concurrent.atomic.AtomicBoolean;
3235
import java.util.concurrent.atomic.AtomicInteger;
3336
import java.util.logging.Logger;
37+
import java.util.stream.Collectors;
3438

3539
import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
3640
import org.apache.maven.surefire.api.provider.AbstractProvider;
@@ -48,8 +52,12 @@
4852
import org.apache.maven.surefire.shared.utils.StringUtils;
4953
import org.junit.platform.engine.DiscoverySelector;
5054
import org.junit.platform.engine.Filter;
55+
import org.junit.platform.engine.FilterResult;
56+
import org.junit.platform.engine.support.descriptor.ClassSource;
57+
import org.junit.platform.engine.support.descriptor.MethodSource;
5158
import org.junit.platform.launcher.EngineFilter;
5259
import org.junit.platform.launcher.LauncherDiscoveryRequest;
60+
import org.junit.platform.launcher.PostDiscoveryFilter;
5361
import org.junit.platform.launcher.TagFilter;
5462
import org.junit.platform.launcher.TestExecutionListener;
5563
import org.junit.platform.launcher.TestIdentifier;
@@ -62,6 +70,7 @@
6270
import static java.util.stream.Collectors.toList;
6371
import static org.apache.maven.surefire.api.booter.ProviderParameterNames.EXCLUDE_JUNIT5_ENGINES_PROP;
6472
import static org.apache.maven.surefire.api.booter.ProviderParameterNames.INCLUDE_JUNIT5_ENGINES_PROP;
73+
import static org.apache.maven.surefire.api.booter.ProviderParameterNames.JUNIT_VINTAGE_DETECTED;
6574
import static org.apache.maven.surefire.api.booter.ProviderParameterNames.TESTNG_EXCLUDEDGROUPS_PROP;
6675
import static org.apache.maven.surefire.api.booter.ProviderParameterNames.TESTNG_GROUPS_PROP;
6776
import static org.apache.maven.surefire.api.report.ConsoleOutputCapture.startCapture;
@@ -228,11 +237,20 @@ private LauncherDiscoveryRequestBuilder newRequest() {
228237
private Filter<?>[] newFilters() {
229238
List<Filter<?>> filters = new ArrayList<>();
230239

231-
getPropertiesList(TESTNG_GROUPS_PROP).map(TagFilter::includeTags).ifPresent(filters::add);
240+
if (!Boolean.parseBoolean(parameters.getProviderProperties().get(JUNIT_VINTAGE_DETECTED))) {
241+
getPropertiesList(TESTNG_GROUPS_PROP).map(TagFilter::includeTags).ifPresent(filters::add);
232242

233-
getPropertiesList(TESTNG_EXCLUDEDGROUPS_PROP)
234-
.map(TagFilter::excludeTags)
235-
.ifPresent(filters::add);
243+
getPropertiesList(TESTNG_EXCLUDEDGROUPS_PROP)
244+
.map(TagFilter::excludeTags)
245+
.ifPresent(filters::add);
246+
} else {
247+
Optional<Class<?>> categoryClass = getCategoryClass();
248+
if (categoryClass.isPresent()) {
249+
getPropertiesList(TESTNG_GROUPS_PROP)
250+
.map(strings -> getIncludeCategoryFilter(strings, categoryClass))
251+
.ifPresent(filters::add);
252+
}
253+
}
236254

237255
of(optionallyWildcardFilter(parameters.getTestRequest().getTestListResolver()))
238256
.filter(f -> !f.isEmpty())
@@ -255,6 +273,87 @@ Filter<?>[] getFilters() {
255273
return filters;
256274
}
257275

276+
PostDiscoveryFilter getIncludeCategoryFilter(List<String> categories, Optional<Class<?>> categoryClass) {
277+
278+
return testDescriptor -> {
279+
Optional<MethodSource> methodSource = testDescriptor
280+
.getSource()
281+
.filter(testSource -> testSource instanceof MethodSource)
282+
.map(testSource -> (MethodSource) testSource);
283+
boolean hasCategoryClass = false, hasCategoryMethod = false;
284+
if (methodSource.isPresent()) {
285+
if (categoryClass.isPresent()) {
286+
hasCategoryClass = hasCategoryAnnotation(
287+
methodSource.get().getJavaMethod(), categoryClass.orElse(null), categories);
288+
}
289+
}
290+
291+
Optional<ClassSource> classSource = testDescriptor
292+
.getSource()
293+
.filter(testSource -> testSource instanceof ClassSource)
294+
.map(testSource -> (ClassSource) testSource);
295+
if (classSource.isPresent()) {
296+
if (categoryClass.isPresent()) {
297+
hasCategoryMethod = hasCategoryAnnotation(
298+
getClass(classSource.get().getClassName()).get(), categoryClass.orElse(null), categories);
299+
}
300+
}
301+
302+
return hasCategoryClass || hasCategoryMethod
303+
? FilterResult.included("Category found")
304+
: FilterResult.excluded("Does not have category annotation");
305+
};
306+
}
307+
308+
private boolean hasCategoryAnnotation(Class<?> clazz, Class<?> categoryClass, List<String> categories) {
309+
Optional<Annotation> anno = stream(clazz.getAnnotations())
310+
.filter(annotation -> annotation.annotationType().equals(categoryClass))
311+
.findFirst();
312+
if (anno.isPresent()) {
313+
List<String> catValue = getCategoryValue(of(anno.get()));
314+
return catValue.stream().anyMatch(categories::contains);
315+
}
316+
return false;
317+
}
318+
319+
private boolean hasCategoryAnnotation(Method method, Class<?> categoryClass, List<String> categories) {
320+
Optional<Annotation> anno = stream(method.getAnnotations())
321+
.filter(annotation -> annotation.annotationType().equals(categoryClass))
322+
.findFirst();
323+
if (anno.isPresent()) {
324+
List<String> catValue = getCategoryValue(of(anno.get()));
325+
return catValue.stream().anyMatch(categories::contains);
326+
}
327+
return false;
328+
}
329+
330+
private Optional<Class<?>> getCategoryClass() {
331+
return getClass("org.junit.experimental.categories.Category");
332+
}
333+
334+
private Optional<Class<?>> getClass(String className) {
335+
Thread currentThread = Thread.currentThread();
336+
try {
337+
return Optional.of(currentThread.getContextClassLoader().loadClass(className));
338+
} catch (Exception e) {
339+
return Optional.empty();
340+
}
341+
}
342+
343+
private List<String> getCategoryValue(Optional<Object> instance) {
344+
Optional<Class<?>> optionalClass = getCategoryClass();
345+
if (optionalClass.isPresent()) {
346+
try {
347+
Class<?>[] classes =
348+
(Class<?>[]) optionalClass.get().getMethod("value").invoke(instance.get());
349+
return stream(classes).map(Class::getName).collect(Collectors.toList());
350+
} catch (Exception e) {
351+
// ignore
352+
}
353+
}
354+
return Collections.emptyList();
355+
}
356+
258357
private Map<String, String> newConfigurationParameters() {
259358
String content = parameters.getProviderProperties().get(CONFIGURATION_PARAMETERS);
260359
if (content == null) {

0 commit comments

Comments
 (0)