Skip to content

Commit

Permalink
Allow element resolvers to return more than one test descriptor
Browse files Browse the repository at this point in the history
  • Loading branch information
jlink authored and bechte committed Apr 29, 2016
1 parent af28022 commit a5d6323
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 24 deletions.
Expand Up @@ -15,6 +15,8 @@
import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
Expand Down Expand Up @@ -86,51 +88,55 @@ private void resolveUniqueId(TestDescriptor parent, List<UniqueId.Segment> remai
} }


private void resolveMethod(Class<?> testClass, Method testMethod) { private void resolveMethod(Class<?> testClass, Method testMethod) {
Set<TestDescriptor> resolvedParentDescriptors = resolve(testClass, engineDescriptor); Set<TestDescriptor> potentialParents = resolve(testClass, engineDescriptor);
resolvedParentDescriptors.forEach(parent -> { resolveElementWithChildren(testMethod, potentialParents);
resolve(testMethod, parent);
});
} }


private void resolveClass(Class<?> testClass) { private void resolveClass(Class<?> testClass) {
TestDescriptor parent = engineDescriptor; Set<TestDescriptor> potentialParents = Collections.singleton(engineDescriptor);
Set<TestDescriptor> resolvedClassDescriptors = resolve(testClass, parent); resolveElementWithChildren(testClass, potentialParents);
resolvedClassDescriptors.forEach(classDescriptor -> { }
resolveChildren(classDescriptor);
private void resolveElementWithChildren(AnnotatedElement element, Set<TestDescriptor> potentialParents) {
Set<TestDescriptor> resolvedDescriptors = new HashSet<>();
potentialParents.forEach(parent -> {
resolvedDescriptors.addAll(resolve(element, parent));
}); });
resolvedDescriptors.forEach(this::resolveChildren);
} }


private void resolveChildren(TestDescriptor descriptor) { private void resolveChildren(TestDescriptor descriptor) {
if (descriptor instanceof ClassTestDescriptor) { if (descriptor instanceof ClassTestDescriptor) {
Class<?> testClass = ((ClassTestDescriptor) descriptor).getTestClass(); Class<?> testClass = ((ClassTestDescriptor) descriptor).getTestClass();
List<Method> testMethodCandidates = findMethods(testClass, method -> !ReflectionUtils.isPrivate(method), List<Method> testMethodCandidates = findMethods(testClass, method -> !ReflectionUtils.isPrivate(method),
ReflectionUtils.MethodSortOrder.HierarchyDown); ReflectionUtils.MethodSortOrder.HierarchyDown);
testMethodCandidates.forEach(method -> resolve(method, descriptor)); testMethodCandidates.forEach(
method -> resolveElementWithChildren(method, Collections.singleton(descriptor)));
} }
} }


private Set<TestDescriptor> resolve(AnnotatedElement element, TestDescriptor parent) { private Set<TestDescriptor> resolve(AnnotatedElement element, TestDescriptor parent) {
return resolvers.stream() // return resolvers.stream() //
.map(resolver -> tryToResolveWithResolver(element, parent, resolver)) // .map(resolver -> tryToResolveWithResolver(element, parent, resolver)) //
.filter(Optional::isPresent) // .filter(testDescriptors -> !testDescriptors.isEmpty()) //
.map(Optional::get) // .flatMap(Collection::stream) //
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }


private Optional<TestDescriptor> tryToResolveWithResolver(AnnotatedElement element, TestDescriptor parent, private Set<TestDescriptor> tryToResolveWithResolver(AnnotatedElement element, TestDescriptor parent,
ElementResolver resolver) { ElementResolver resolver) {
if (!resolver.canResolveElement(element, parent)) if (!resolver.canResolveElement(element, parent))
return Optional.empty(); return Collections.emptySet();


UniqueId uniqueId = resolver.createUniqueId(element, parent); UniqueId uniqueId = resolver.createUniqueId(element, parent);


Optional<TestDescriptor> optionalMethodTestDescriptor = findTestDescriptorByUniqueId(uniqueId); Optional<TestDescriptor> optionalMethodTestDescriptor = findTestDescriptorByUniqueId(uniqueId);
if (optionalMethodTestDescriptor.isPresent()) if (optionalMethodTestDescriptor.isPresent())
return optionalMethodTestDescriptor; return Collections.singleton(optionalMethodTestDescriptor.get());


TestDescriptor newDescriptor = resolver.resolve(element, parent, uniqueId); Set<TestDescriptor> newDescriptors = resolver.resolve(element, parent, uniqueId);
parent.addChild(newDescriptor); newDescriptors.forEach(parent::addChild);
return Optional.of(newDescriptor); return newDescriptors;
} }


@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Expand Down
Expand Up @@ -11,6 +11,7 @@
package org.junit.gen5.engine.junit5.discoveryNEW; package org.junit.gen5.engine.junit5.discoveryNEW;


import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.util.Set;


import org.junit.gen5.engine.TestDescriptor; import org.junit.gen5.engine.TestDescriptor;
import org.junit.gen5.engine.UniqueId; import org.junit.gen5.engine.UniqueId;
Expand All @@ -19,11 +20,24 @@ public interface ElementResolver {


boolean canResolveElement(AnnotatedElement element, TestDescriptor parent); boolean canResolveElement(AnnotatedElement element, TestDescriptor parent);


/**
* Will only be called if {@linkplain #canResolveElement(AnnotatedElement, TestDescriptor)} returns true.
*/
UniqueId createUniqueId(AnnotatedElement element, TestDescriptor parent); UniqueId createUniqueId(AnnotatedElement element, TestDescriptor parent);


TestDescriptor resolve(AnnotatedElement element, TestDescriptor parent, UniqueId uniqueId); /**
* Will only be called if {@linkplain #canResolveElement(AnnotatedElement, TestDescriptor)} returns true.
*
* <p>Must return a non empty {@code Set<TestDescriptor>}
*/
Set<TestDescriptor> resolve(AnnotatedElement element, TestDescriptor parent, UniqueId uniqueId);


boolean canResolveUniqueId(UniqueId.Segment segment, TestDescriptor parent); boolean canResolveUniqueId(UniqueId.Segment segment, TestDescriptor parent);


/**
* Will only be called if {@linkplain #canResolveUniqueId(UniqueId.Segment, TestDescriptor)} returns true.
*
* <p>Must return a valid {@linkplain TestDescriptor testDescriptor}.
*/
TestDescriptor resolve(UniqueId.Segment segment, TestDescriptor parent, UniqueId uniqueId); TestDescriptor resolve(UniqueId.Segment segment, TestDescriptor parent, UniqueId uniqueId);
} }
Expand Up @@ -11,7 +11,9 @@
package org.junit.gen5.engine.junit5.discoveryNEW; package org.junit.gen5.engine.junit5.discoveryNEW;


import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.util.Collections;
import java.util.Optional; import java.util.Optional;
import java.util.Set;


import org.junit.gen5.commons.util.ReflectionUtils; import org.junit.gen5.commons.util.ReflectionUtils;
import org.junit.gen5.engine.TestDescriptor; import org.junit.gen5.engine.TestDescriptor;
Expand All @@ -38,8 +40,8 @@ public UniqueId createUniqueId(AnnotatedElement element, TestDescriptor parent)
} }


@Override @Override
public TestDescriptor resolve(AnnotatedElement element, TestDescriptor parent, UniqueId uniqueId) { public Set<TestDescriptor> resolve(AnnotatedElement element, TestDescriptor parent, UniqueId uniqueId) {
return resolveClass((Class<?>) element, parent, uniqueId); return Collections.singleton(resolveClass((Class<?>) element, parent, uniqueId));
} }


@Override @Override
Expand All @@ -56,8 +58,7 @@ public boolean canResolveUniqueId(UniqueId.Segment segment, TestDescriptor paren
@Override @Override
public TestDescriptor resolve(UniqueId.Segment segment, TestDescriptor parent, UniqueId uniqueId) { public TestDescriptor resolve(UniqueId.Segment segment, TestDescriptor parent, UniqueId uniqueId) {
Optional<Class<?>> optionalContainerClass = ReflectionUtils.loadClass(segment.getValue()); Optional<Class<?>> optionalContainerClass = ReflectionUtils.loadClass(segment.getValue());

return resolveClass(optionalContainerClass.get(), parent, uniqueId);
return resolve(optionalContainerClass.get(), parent, uniqueId);
} }


private TestDescriptor resolveClass(Class<?> testClass, TestDescriptor parent, UniqueId uniqueId) { private TestDescriptor resolveClass(Class<?> testClass, TestDescriptor parent, UniqueId uniqueId) {
Expand Down
Expand Up @@ -12,6 +12,8 @@


import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Set;


import org.junit.gen5.engine.TestDescriptor; import org.junit.gen5.engine.TestDescriptor;
import org.junit.gen5.engine.UniqueId; import org.junit.gen5.engine.UniqueId;
Expand All @@ -38,8 +40,8 @@ public UniqueId createUniqueId(AnnotatedElement element, TestDescriptor parent)
} }


@Override @Override
public TestDescriptor resolve(AnnotatedElement element, TestDescriptor parent, UniqueId uniqueId) { public Set<TestDescriptor> resolve(AnnotatedElement element, TestDescriptor parent, UniqueId uniqueId) {
return resolveMethod((Method) element, (ClassTestDescriptor) parent, uniqueId); return Collections.singleton(resolveMethod((Method) element, (ClassTestDescriptor) parent, uniqueId));
} }


@Override @Override
Expand Down

0 comments on commit a5d6323

Please sign in to comment.