CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-junit-platform--junit-platform-engine

JUnit Platform Engine API - Core engine API for implementing custom test engines in the JUnit Platform ecosystem

Pending
Overview
Eval results
Files

engine-implementation.mddocs/

Engine Implementation

Core TestEngine interface and related classes that provide the foundation for implementing custom test engines in the JUnit Platform.

Capabilities

TestEngine Interface

The main interface that all custom test engines must implement to integrate with the JUnit Platform launcher.

/**
 * Main interface for test engines. Provides engine identification, test discovery, and execution capabilities.
 */
public interface TestEngine {
    /**
     * Get the unique identifier for this test engine.
     * @return the engine ID (must be unique across all engines)
     */
    String getId();
    
    /**
     * Discover tests from the provided discovery request.
     * @param discoveryRequest the discovery request containing selectors and filters
     * @param uniqueId the unique ID for the engine's root descriptor
     * @return the root test descriptor containing discovered tests
     */
    TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId);
    
    /**
     * Execute the tests described by the execution request.
     * @param request the execution request containing test descriptors and configuration
     */
    void execute(ExecutionRequest request);
    
    /**
     * Get the Maven group ID of this engine.
     * @return optional group ID for engine metadata
     */
    default Optional<String> getGroupId() {
        return Optional.empty();
    }
    
    /**
     * Get the Maven artifact ID of this engine.
     * Default implementation tries to get module name first, then implementation title from package attributes.
     * @return optional artifact ID for engine metadata
     */
    default Optional<String> getArtifactId() {
        Optional<String> moduleName = ModuleUtils.getModuleName(getClass());
        if (moduleName.isPresent()) {
            return moduleName;
        }
        return PackageUtils.getAttribute(getClass(), Package::getImplementationTitle);
    }
    
    /**
     * Get the version of this engine.
     * Default implementation tries "Engine-Version-" + getId() attribute first, 
     * then module or implementation version, defaulting to "DEVELOPMENT".
     * @return optional version for engine metadata
     */
    default Optional<String> getVersion() {
        Optional<String> standalone = PackageUtils.getAttribute(getClass(), "Engine-Version-" + getId());
        if (standalone.isPresent()) {
            return standalone;
        }
        return Optional.of(PackageUtils.getModuleOrImplementationVersion(getClass()).orElse("DEVELOPMENT"));
    }
}

Usage Example:

import org.junit.platform.engine.*;
import org.junit.platform.engine.discovery.*;
import org.junit.platform.engine.support.descriptor.EngineDescriptor;
import org.junit.platform.commons.util.ModuleUtils;
import org.junit.platform.commons.util.PackageUtils;

public class CustomTestEngine implements TestEngine {
    public static final String ENGINE_ID = "custom-engine";
    
    @Override
    public String getId() {
        return ENGINE_ID;
    }
    
    @Override
    public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) {
        EngineDescriptor engineDescriptor = new EngineDescriptor(uniqueId, "Custom Engine");
        
        // Process class selectors
        discoveryRequest.getSelectorsByType(ClassSelector.class)
            .forEach(selector -> {
                Class<?> testClass = selector.getJavaClass();
                if (isTestClass(testClass)) {
                    TestDescriptor classDescriptor = createClassDescriptor(testClass, engineDescriptor);
                    engineDescriptor.addChild(classDescriptor);
                    
                    // Discover test methods within the class
                    discoverTestMethods(testClass, classDescriptor);
                }
            });
        
        return engineDescriptor;
    }
    
    @Override
    public void execute(ExecutionRequest request) {
        TestDescriptor rootDescriptor = request.getRootTestDescriptor();
        EngineExecutionListener listener = request.getEngineExecutionListener();
        ConfigurationParameters config = request.getConfigurationParameters();
        
        executeDescriptor(rootDescriptor, listener, config);
    }
    
    private void executeDescriptor(TestDescriptor descriptor, 
                                 EngineExecutionListener listener,
                                 ConfigurationParameters config) {
        listener.executionStarted(descriptor);
        
        try {
            if (descriptor.getType() == TestDescriptor.Type.TEST) {
                // Execute actual test logic
                executeTest(descriptor, config);
                listener.executionFinished(descriptor, TestExecutionResult.successful());
            } else {
                // Execute children for containers
                descriptor.getChildren().forEach(child -> 
                    executeDescriptor(child, listener, config));
                listener.executionFinished(descriptor, TestExecutionResult.successful());
            }
        } catch (Exception e) {
            listener.executionFinished(descriptor, TestExecutionResult.failed(e));
        }
    }
}

TestExecutionResult

Encapsulates the result of executing a test or container, including success, failure, or abortion status.

/**
 * Result of executing a test or container.
 */
public final class TestExecutionResult {
    /**
     * Create a successful execution result.
     * @return successful result
     */
    public static TestExecutionResult successful();
    
    /**
     * Create a failed execution result.
     * @param throwable the cause of failure
     * @return failed result with throwable
     */
    public static TestExecutionResult failed(Throwable throwable);
    
    /**
     * Create an aborted execution result.
     * @param throwable the cause of abortion
     * @return aborted result with throwable
     */
    public static TestExecutionResult aborted(Throwable throwable);
    
    /**
     * Get the execution status.
     * @return the status (SUCCESSFUL, FAILED, or ABORTED)
     */
    public Status getStatus();
    
    /**
     * Get the throwable associated with this result.
     * @return optional throwable for failed/aborted results
     */
    public Optional<Throwable> getThrowable();
    
    /**
     * Execution status enumeration.
     */
    public enum Status { SUCCESSFUL, ABORTED, FAILED }
}

UniqueId

Encapsulates the creation, parsing, and display of unique identifiers for test descriptors within the engine hierarchy.

/**
 * Unique identifier for test descriptors, supporting hierarchical structure.
 */
public final class UniqueId implements Serializable, Cloneable {
    /**
     * Parse a unique ID from string representation.
     * @param uniqueId string representation of unique ID
     * @return parsed UniqueId
     */
    public static UniqueId parse(String uniqueId);
    
    /**
     * Create a root unique ID for an engine.
     * @param engineId the engine identifier
     * @return root UniqueId for the engine
     */
    public static UniqueId forEngine(String engineId);
    
    /**
     * Create a root unique ID with custom type and value.
     * @param type the segment type
     * @param value the segment value
     * @return root UniqueId
     */
    public static UniqueId root(String type, String value);
    
    /**
     * Append a new segment to this unique ID.
     * @param type the segment type
     * @param value the segment value
     * @return new UniqueId with appended segment
     */
    public UniqueId append(String type, String value);
    
    /**
     * Get all segments of this unique ID.
     * @return immutable list of segments
     */
    public List<Segment> getSegments();
    
    /**
     * Get the engine ID if this is an engine-level unique ID.
     * @return optional engine ID
     */
    public Optional<String> getEngineId();
    
    /**
     * Individual segment of a unique ID.
     */
    public static final class Segment {
        public String getType();
        public String getValue();
    }
}

Usage Example:

// Create engine root ID
UniqueId engineId = UniqueId.forEngine("my-engine");

// Build hierarchical IDs
UniqueId classId = engineId.append("class", "com.example.TestClass");
UniqueId methodId = classId.append("method", "testMethod");

// Parse from string
UniqueId parsed = UniqueId.parse("[engine:my-engine]/[class:com.example.TestClass]/[method:testMethod]");

TestTag

Immutable value object representing tags for categorizing and filtering tests.

/**
 * Immutable value object for test tags.
 */
public final class TestTag implements Serializable {
    /**
     * Validate tag name syntax.
     * @param name the tag name to validate
     * @return true if valid, false otherwise
     */
    public static boolean isValid(String name);
    
    /**
     * Create a test tag.
     * @param name the tag name (must be valid)
     * @return TestTag instance
     */
    public static TestTag create(String name);
    
    /**
     * Get the tag name.
     * @return the tag name
     */
    public String getName();
    
    /**
     * Set of characters not allowed in tag names.
     */
    public static final Set<Character> RESERVED_CHARACTERS;
}

TestSource Interface

Marker interface for representing the source location of tests (classes, methods, files, etc.).

/**
 * Marker interface for test source locations.
 */
public interface TestSource extends Serializable {
    // Marker interface - implementations provide specific source types
}

Common TestSource implementations are provided in the org.junit.platform.engine.support.descriptor package for classes, methods, files, directories, URIs, and other source types.

Install with Tessl CLI

npx tessl i tessl/maven-org-junit-platform--junit-platform-engine

docs

config-storage.md

engine-implementation.md

hierarchical-engine.md

index.md

test-descriptors.md

test-discovery.md

test-execution.md

tile.json