JUnit Platform Engine API - Core engine API for implementing custom test engines in the JUnit Platform ecosystem
npx @tessl/cli install tessl/maven-org-junit-platform--junit-platform-engine@1.13.0The JUnit Platform Engine API provides the foundational infrastructure for implementing custom test engines in the JUnit Platform ecosystem. This library defines the core interfaces and contracts that test engines must implement to integrate with the JUnit Platform launcher, enabling diverse testing approaches to run within a unified platform.
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-engine</artifactId>
<version>1.13.4</version>
</dependency>import org.junit.platform.engine.TestEngine;
import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.ExecutionRequest;
import org.junit.platform.engine.EngineDiscoveryRequest;
import org.junit.platform.engine.UniqueId;import org.junit.platform.engine.*;
import org.junit.platform.engine.support.descriptor.EngineDescriptor;
// Example: Basic test engine implementation
public class MyTestEngine implements TestEngine {
private static final String ENGINE_ID = "my-test-engine";
@Override
public String getId() {
return ENGINE_ID;
}
@Override
public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest,
UniqueId uniqueId) {
// Create root descriptor for this engine
TestDescriptor engineDescriptor = new EngineDescriptor(uniqueId, "My Test Engine");
// Discovery logic: find tests based on selectors and filters
discoveryRequest.getSelectorsByType(ClassSelector.class)
.forEach(selector -> {
// Add discovered tests as children
// engineDescriptor.addChild(createTestDescriptor(...));
});
return engineDescriptor;
}
@Override
public void execute(ExecutionRequest request) {
TestDescriptor rootDescriptor = request.getRootTestDescriptor();
EngineExecutionListener listener = request.getEngineExecutionListener();
// Execute tests and notify listener of results
listener.executionStarted(rootDescriptor);
// ... execute children ...
listener.executionFinished(rootDescriptor, TestExecutionResult.successful());
}
}The JUnit Platform Engine API is built around several key abstractions:
The fundamental TestEngine interface that all custom test engines must implement to integrate with the JUnit Platform.
public interface TestEngine {
String getId();
TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId);
void execute(ExecutionRequest request);
Optional<String> getGroupId();
Optional<String> getArtifactId();
Optional<String> getVersion();
}Comprehensive test discovery system with selectors for finding tests and filters for refining discovery results.
public interface EngineDiscoveryRequest {
<T extends DiscoverySelector> List<T> getSelectorsByType(Class<T> selectorType);
<T extends DiscoveryFilter<?>> List<T> getFiltersByType(Class<T> filterType);
ConfigurationParameters getConfigurationParameters();
EngineDiscoveryListener getDiscoveryListener();
}
// Factory for creating discovery selectors
public final class DiscoverySelectors {
public static ClassSelector selectClass(Class<?> clazz);
public static MethodSelector selectMethod(Class<?> clazz, String methodName);
public static PackageSelector selectPackage(String packageName);
public static UriSelector selectUri(URI uri);
// ... many more selector factory methods
}Test execution infrastructure providing contexts, listeners, and result reporting for test engines.
public final class ExecutionRequest {
public TestDescriptor getRootTestDescriptor();
public EngineExecutionListener getEngineExecutionListener();
public ConfigurationParameters getConfigurationParameters();
public NamespacedHierarchicalStore<Namespace> getStore();
}
public interface EngineExecutionListener {
void executionStarted(TestDescriptor testDescriptor);
void executionFinished(TestDescriptor testDescriptor, TestExecutionResult result);
void executionSkipped(TestDescriptor testDescriptor, String reason);
void dynamicTestRegistered(TestDescriptor testDescriptor);
void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry entry);
}Hierarchical test descriptor system for representing discovered tests and containers with metadata, sources, and relationships.
public interface TestDescriptor {
UniqueId getUniqueId();
String getDisplayName();
Set<TestTag> getTags();
Optional<TestSource> getSource();
void addChild(TestDescriptor child);
void removeChild(TestDescriptor child);
Set<? extends TestDescriptor> getChildren();
Type getType();
enum Type { CONTAINER, TEST, CONTAINER_AND_TEST }
}Framework for building hierarchical test engines with parallel execution, resource management, and structured execution contexts.
public abstract class HierarchicalTestEngine<C extends EngineExecutionContext>
implements TestEngine {
protected abstract C createExecutionContext(ExecutionRequest request);
protected HierarchicalTestExecutorService createExecutorService(ExecutionRequest request);
}
public interface Node<C extends EngineExecutionContext> {
C prepare(C context) throws Exception;
SkipResult shouldBeSkipped(C context) throws Exception;
C before(C context) throws Exception;
C execute(C context, DynamicTestExecutor dynamicTestExecutor) throws Exception;
void after(C context) throws Exception;
void cleanUp(C context) throws Exception;
}Configuration system and hierarchical storage for test engines to manage parameters and test-scoped data.
public interface ConfigurationParameters {
Optional<String> get(String key);
Optional<Boolean> getBoolean(String key);
<T> Optional<T> get(String key, Function<String, T> transformer);
Set<String> keySet();
}
public final class NamespacedHierarchicalStore<N> implements AutoCloseable {
public Object get(N namespace, Object key);
public <T> T get(N namespace, Object key, Class<T> requiredType);
public Object put(N namespace, Object key, Object value);
public <K, V> Object getOrComputeIfAbsent(N namespace, K key, Function<K, V> defaultCreator);
public void close() throws Exception;
}