Skip to content

Commit

Permalink
Add support for UniqueId selectors
Browse files Browse the repository at this point in the history
  • Loading branch information
alextu committed Sep 27, 2022
1 parent f2de1f0 commit c299772
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 25 deletions.
4 changes: 3 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ dependencies {
compileOnly("org.scalatest:scalatest_2.11:3.3.0-SNAP3")

testImplementation("org.junit.jupiter:junit-jupiter-api:$junitJupiterVersion")
testImplementation("org.junit.platform:junit-platform-launcher:$junitPlatformVersion")
testImplementation("org.junit.jupiter:junit-jupiter-engine:$junitJupiterVersion")
testImplementation("org.junit.jupiter:junit-jupiter-params:$junitJupiterVersion")
testImplementation("org.junit.platform:junit-platform-launcher:$junitPlatformVersion")
testImplementation("org.junit.platform:junit-platform-testkit:$junitPlatformVersion")
testImplementation("org.junit.platform:junit-platform-engine:1.6.0")
testImplementation("org.scalatest:scalatest_$testScalaLibraryVersion:3.3.0-SNAP3")
testImplementation("org.scala-lang:scala-library:$testScalaVersion")
Expand Down
58 changes: 43 additions & 15 deletions src/main/java/co/helmethair/scalatest/ScalatestEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,24 @@
import co.helmethair.scalatest.reporter.JUnitReporter;
import co.helmethair.scalatest.runtime.Discovery;
import co.helmethair.scalatest.runtime.Executor;
import org.junit.platform.engine.*;
import org.junit.platform.engine.ConfigurationParameters;
import org.junit.platform.engine.EngineDiscoveryRequest;
import org.junit.platform.engine.ExecutionRequest;
import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.TestEngine;
import org.junit.platform.engine.UniqueId;
import org.junit.platform.engine.discovery.ClassSelector;
import org.scalatest.DoNotDiscover;
import org.scalatest.Suite;
import org.junit.platform.engine.discovery.UniqueIdSelector;

import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static co.helmethair.scalatest.descriptor.ScalatestDescriptor.SUITE_TYPE;

public class ScalatestEngine implements TestEngine {
public static final String ID = "scalatest";
public static final String PARAMETER_SKIP_AFTER_FAIL = "scalatest.junit.skip_after_fail";
Expand All @@ -29,9 +37,16 @@ public String getId() {
public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) {
ScalatestEngineDescriptor engineDescriptor = new ScalatestEngineDescriptor(uniqueId, ID);

List<Class<? extends Suite>> classes = discoverClassSelectors(discoveryRequest);
return runtime.discover(engineDescriptor,
union(discoverClassSelectors(discoveryRequest), discoverUniqueIdSelectors(discoveryRequest)),
Thread.currentThread().getContextClassLoader());
}

return runtime.discover(engineDescriptor, classes, Thread.currentThread().getContextClassLoader());
private Set<String> union(List<String> sel1, List<String> sel2) {
Set<String> classes = new LinkedHashSet<>();
classes.addAll(sel1);
classes.addAll(sel2);
return Collections.unmodifiableSet(classes);
}

@Override
Expand All @@ -46,14 +61,27 @@ public void execute(ExecutionRequest executionRequest) {
executor.executeTest(executionRequest.getRootTestDescriptor(), reporter);
}

@SuppressWarnings("unchecked")
private List<Class<? extends Suite>> discoverClassSelectors(EngineDiscoveryRequest dicoveryRequest) {
return dicoveryRequest.getSelectorsByType(ClassSelector.class).stream().map(ClassSelector::getJavaClass)
.filter(c -> !(c.getEnclosingMethod() != null //only local or anonymous classes have an enclosing method
|| c.isSynthetic()
|| Modifier.isAbstract(c.getModifiers())
|| c.getAnnotation(DoNotDiscover.class) != null)
&& Suite.class.isAssignableFrom(c)
).map(c -> ((Class<? extends Suite>) c)).collect(Collectors.toList());
private List<String> discoverUniqueIdSelectors(EngineDiscoveryRequest discoveryRequest) {
return discoveryRequest.getSelectorsByType(UniqueIdSelector.class).stream()
.map(this::getSuite)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
}

private Optional<String> getSuite(UniqueIdSelector u) {
UniqueId uniqueId = u.getUniqueId();
if (uniqueId.hasPrefix(UniqueId.forEngine(ID))) {
UniqueId.Segment segment = uniqueId.getSegments().get(1);
if (SUITE_TYPE.equals(segment.getType())) {
return Optional.of(segment.getValue());
}
}
return Optional.empty();
}

private List<String> discoverClassSelectors(EngineDiscoveryRequest discoveryRequest) {
return discoveryRequest.getSelectorsByType(ClassSelector.class).stream().map(ClassSelector::getClassName)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
public abstract class ScalatestDescriptor implements TestDescriptor {
final static UniqueId ENGINE_ID = UniqueId.forEngine(ScalatestEngine.ID);
static final ConcurrentHashMap<UniqueId, ScalatestDescriptor> descriptorsById = new ConcurrentHashMap<>();
public static final String SUITE_TYPE = "suite";
private final UniqueId id;
private TestDescriptor parentDescriptor = null;
private Set<TestDescriptor> childDescriptors = new HashSet<TestDescriptor>();
Expand All @@ -32,11 +33,11 @@ public static Optional<ScalatestDescriptor> findById(UniqueId uniqueId) {
}

static UniqueId testId(String suiteId, String testName) {
return ENGINE_ID.append("suite", suiteId).append("test", testName);
return ENGINE_ID.append(SUITE_TYPE, suiteId).append("test", testName);
}

static UniqueId containerId(String suiteId) {
return ENGINE_ID.append("suite", suiteId);
return ENGINE_ID.append(SUITE_TYPE, suiteId);
}

static UniqueId descriptorId(String suiteId, String testName) {
Expand Down
37 changes: 31 additions & 6 deletions src/main/java/co/helmethair/scalatest/runtime/Discovery.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,56 @@
import co.helmethair.scalatest.scala.ScalaConversions;
import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.TestTag;
import org.scalatest.DoNotDiscover;
import org.scalatest.Suite;
import org.scalatest.TagAnnotation;
import scala.Option;

import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.Collections.*;

public class Discovery {

public ScalatestEngineDescriptor discover(ScalatestEngineDescriptor engineDescriptor, List<Class<? extends Suite>> classes, ClassLoader classLoader) {
@SuppressWarnings("unchecked")
public ScalatestEngineDescriptor discover(ScalatestEngineDescriptor engineDescriptor, Set<String> classes, ClassLoader classLoader) {
classes.forEach(c -> {
Class<?> aClass = null;
try {
Suite suite = ((Suite) classLoader.loadClass(c.getName()).newInstance());
addSuite(suite, engineDescriptor);
aClass = classLoader.loadClass(c);
if (isScalaSuite(aClass)) {
Suite suite = ((Suite) aClass.newInstance());
addSuite(suite, engineDescriptor);
}
} catch (Throwable e) {
addFailedInit(e, c, engineDescriptor);
if (aClass != null && Suite.class.isAssignableFrom(aClass)) {
addFailedInit(e, (Class<? extends Suite>) aClass, engineDescriptor);
} else {
addFailedInit(e, c, engineDescriptor);
}
}
});

return engineDescriptor;
}

private boolean isScalaSuite(Class<?> c) {
return !(c.getEnclosingMethod() != null //only local or anonymous classes have an enclosing method
|| c.isSynthetic()
|| Modifier.isAbstract(c.getModifiers())
|| c.getAnnotation(DoNotDiscover.class) != null)
&& Suite.class.isAssignableFrom(c);
}

private void addFailedInit(Throwable cause, String className, TestDescriptor parent) {
ScalatestFailedInitDescriptor failed = new ScalatestFailedInitDescriptor(cause, className, emptySet());
linkChild(parent, failed);
}

private void addFailedInit(Throwable cause, Class<? extends Suite> clazz, TestDescriptor parent) {
String className = clazz.getName();
ScalatestFailedInitDescriptor failed = new ScalatestFailedInitDescriptor(cause, className, extractTags(clazz));
Expand Down Expand Up @@ -74,6 +99,6 @@ private Set<TestTag> getTags(Suite scalasuite, String testName) {
return ScalaConversions.setAsJavaSet(tagSetOption.get()).stream()
.map(TestTag::create).collect(Collectors.toSet());
}
return Collections.emptySet();
return emptySet();
}
}
26 changes: 26 additions & 0 deletions src/test/java/co/helmethair/scalatest/UniqueIdTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package co.helmethair.scalatest;

import co.helmethair.scalatest.helper.TestHelpers;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.platform.engine.discovery.DiscoverySelectors;
import org.junit.platform.testkit.engine.EngineTestKit;

public class UniqueIdTest implements TestHelpers {

@ParameterizedTest
@CsvSource({"[engine:scalatest]/[suite:tests.NestedTest], 2, 0",
// For now, it does not support really executing the selected test, it will execute the whole suite
"[engine:scalatest]/[suite:tests.NestedTest]/[test:nested test1], 2, 0",
"[engine:scalatest]/[foo:tests.NestedTest], 0, 0",
"[engine:scalatest]/[suite:tests.UnknownFoo], 0, 1",
})
void handleUniqueId(String id, int successEvents, int failingEvents) {
EngineTestKit
.engine("scalatest")
.selectors(DiscoverySelectors.selectUniqueId(id))
.execute()
.testEvents()
.assertStatistics(stats -> stats.succeeded(successEvents).failed(failingEvents));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public <T extends DiscoverySelector> List<T> getSelectorsByType(Class<T> selecto
if (selectorType == ClassSelector.class) {
return ((List<T>) Arrays.stream(classNames).map(DiscoverySelectors::selectClass).collect(Collectors.toList()));
}
return null;
return Collections.emptyList();
}

@Override
Expand Down

0 comments on commit c299772

Please sign in to comment.