CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-junit-jupiter--junit-jupiter-api

JUnit Jupiter API for writing tests - Core API module of JUnit 5 that provides annotations, assertions, and test lifecycle management

Pending
Overview
Eval results
Files

parallel-io.mddocs/

Parallel Execution and I/O Support

Thread-safe test execution with resource management, temporary directory support, and execution control annotations. This module provides capabilities for running tests concurrently while ensuring proper resource isolation and file system operations.

Capabilities

Parallel Execution Control

Configure how tests execute in relation to each other and control thread usage.

/**
 * Configure parallel execution mode for test classes and methods
 */
@Execution(ExecutionMode value)

/**
 * Execute test in isolation (forces sequential execution)
 */
@Isolated

/**
 * Execution mode enumeration
 */
enum ExecutionMode {
    /**
     * Execute in same thread as parent
     */
    SAME_THREAD,
    
    /**
     * Execute concurrently when parallel execution is enabled
     */
    CONCURRENT
}

Usage Examples:

import org.junit.jupiter.api.parallel.*;
import org.junit.jupiter.api.execution.ExecutionMode;

// Class-level parallel execution
@Execution(ExecutionMode.CONCURRENT)
class ParallelTest {

    @Test
    @Execution(ExecutionMode.CONCURRENT)
    void concurrentTest1() {
        // Runs concurrently with other concurrent tests
        performIndependentCalculation();
    }

    @Test
    @Execution(ExecutionMode.CONCURRENT)
    void concurrentTest2() {
        // Can run in parallel with concurrentTest1
        performAnotherIndependentCalculation();
    }

    @Test
    @Execution(ExecutionMode.SAME_THREAD)
    void sequentialTest() {
        // Always runs in same thread as parent
        performThreadSensitiveOperation();
    }
}

// Force sequential execution for entire class
@Execution(ExecutionMode.SAME_THREAD)
class SequentialTest {
    
    @Test
    void test1() {
        // Always sequential due to class-level annotation
    }
    
    @Test
    void test2() {
        // Runs after test1 completes
    }
}

// Isolation for tests that cannot run concurrently with anything
@Isolated
class IsolatedTest {
    
    @Test
    void isolatedTest() {
        // No other tests run concurrently with this
        modifyGlobalState();
    }
}

Resource Management

Declare dependencies on shared resources to prevent concurrent access conflicts.

/**
 * Declare a resource dependency with access mode
 */
@ResourceLock(String value, ResourceAccessMode mode = ResourceAccessMode.READ_WRITE)

/**
 * Multiple resource locks
 */
@ResourceLocks({
    @ResourceLock(value = "resource1", mode = ResourceAccessMode.READ),
    @ResourceLock(value = "resource2", mode = ResourceAccessMode.READ_WRITE)
})

/**
 * Resource access modes
 */
enum ResourceAccessMode {
    /**
     * Read-only access - multiple readers allowed
     */
    READ,
    
    /**
     * Read-write access - exclusive access required
     */
    READ_WRITE
}

/**
 * Programmatic resource lock provider
 */
interface ResourceLocksProvider {
    java.util.Set<Lock> provideForNestedClass(Class<?> testClass);
    java.util.Set<Lock> provideForMethod(Class<?> testClass, java.lang.reflect.Method testMethod);
}

Usage Examples:

import org.junit.jupiter.api.parallel.*;

class ResourceLockTest {

    @Test
    @ResourceLock(value = "database", mode = ResourceAccessMode.READ_WRITE)
    void exclusiveDatabaseTest() {
        // Exclusive access to database resource
        database.createTable("test_table");
        database.insertData("test_data");
        // No other database tests run concurrently
    }

    @Test
    @ResourceLock(value = "database", mode = ResourceAccessMode.READ)
    void readOnlyDatabaseTest1() {
        // Can run concurrently with other READ mode tests
        List<String> tables = database.listTables();
        assertFalse(tables.isEmpty());
    }

    @Test
    @ResourceLock(value = "database", mode = ResourceAccessMode.READ)
    void readOnlyDatabaseTest2() {
        // Can run concurrently with readOnlyDatabaseTest1
        int count = database.getTableCount();
        assertTrue(count >= 0);
    }

    @Test
    @ResourceLocks({
        @ResourceLock(value = "file.system", mode = ResourceAccessMode.READ_WRITE),
        @ResourceLock(value = "network", mode = ResourceAccessMode.READ)
    })
    void multipleResourceTest() {
        // Exclusive file system access, shared network access
        File tempFile = new File("temp.txt");
        tempFile.createNewFile();
        
        NetworkService.readConfiguration(); // Read-only network access
    }
}

// Built-in resource constants
class SystemResourceTest {
    
    @Test
    @ResourceLock(Resources.SYSTEM_PROPERTIES)
    void systemPropertiesTest() {
        // Exclusive access to system properties
        String oldValue = System.getProperty("test.property");
        System.setProperty("test.property", "test-value");
        try {
            // Test logic
        } finally {
            if (oldValue != null) {
                System.setProperty("test.property", oldValue);
            } else {
                System.clearProperty("test.property");
            }
        }
    }

    @Test
    @ResourceLock(Resources.SYSTEM_OUT)
    void systemOutTest() {
        // Exclusive access to System.out
        PrintStream originalOut = System.out;
        ByteArrayOutputStream capturedOutput = new ByteArrayOutputStream();
        System.setOut(new PrintStream(capturedOutput));
        
        try {
            System.out.println("Test output");
            assertEquals("Test output\n", capturedOutput.toString());
        } finally {
            System.setOut(originalOut);
        }
    }
}

Built-in Resource Constants

Predefined resource identifiers for common shared resources.

/**
 * Predefined resource constants for common system resources
 */
class Resources {
    /**
     * System properties resource
     */
    static final String SYSTEM_PROPERTIES = "java.lang.System.properties";
    
    /**
     * System.out resource
     */
    static final String SYSTEM_OUT = "java.lang.System.out";
    
    /**
     * System.err resource
     */
    static final String SYSTEM_ERR = "java.lang.System.err";
    
    /**
     * Default locale resource
     */
    static final String LOCALE = "java.util.Locale.default";
}

Temporary Directory Support

Automatic creation and cleanup of temporary directories for tests.

/**
 * Inject temporary directory into test parameter or field
 */
@TempDir(
    CleanupMode cleanup = CleanupMode.DEFAULT,
    TempDirFactory factory = TempDirFactory.Standard.class
)

/**
 * Cleanup modes for temporary directories
 */
enum CleanupMode {
    /**
     * Use default cleanup behavior (clean up after test completion)
     */
    DEFAULT,
    
    /**
     * Always clean up temporary directory
     */
    ALWAYS,
    
    /**
     * Clean up only if test succeeds
     */
    ON_SUCCESS,
    
    /**
     * Never clean up temporary directory
     */
    NEVER
}

/**
 * Factory for creating temporary directories
 */
interface TempDirFactory extends java.io.Closeable {
    /**
     * Create a new temporary directory
     * @param elementContext the context of the field or parameter where @TempDir is declared
     * @param extensionContext the current extension context
     * @return the path to the newly created temporary directory
     * @throws Exception in case of failures
     */
    java.nio.file.Path createTempDirectory(java.lang.reflect.AnnotatedElement elementContext, ExtensionContext extensionContext) throws Exception;
    
    /**
     * Close resources - default implementation does nothing
     */
    @Override
    default void close() throws java.io.IOException;
    
    /**
     * Standard implementation using Files.createTempDirectory() with "junit-" prefix
     */
    class Standard implements TempDirFactory {
        public static final TempDirFactory INSTANCE = new Standard();
        
        @Override
        public java.nio.file.Path createTempDirectory(java.lang.reflect.AnnotatedElement elementContext, ExtensionContext extensionContext) throws java.io.IOException;
    }
}

Usage Examples:

import org.junit.jupiter.api.io.*;
import java.nio.file.*;

class TempDirectoryTest {

    // Field injection
    @TempDir
    Path tempDirectory;

    // Alternative field injection with File type
    @TempDir
    File tempDir;

    @Test
    void testWithFieldInjection() throws Exception {
        // Use tempDirectory field
        Path testFile = tempDirectory.resolve("test.txt");
        Files.write(testFile, "Hello World".getBytes());
        
        assertTrue(Files.exists(testFile));
        assertEquals("Hello World", Files.readString(testFile));
        
        // Also works with File type
        File anotherFile = new File(tempDir, "another.txt");
        assertTrue(anotherFile.createNewFile());
    }

    @Test
    void testWithParameterInjection(@TempDir Path tempDir) throws Exception {
        // Parameter injection
        Path configFile = tempDir.resolve("config.properties");
        Properties props = new Properties();
        props.setProperty("key", "value");
        
        try (OutputStream out = Files.newOutputStream(configFile)) {
            props.store(out, "Test configuration");
        }
        
        assertTrue(Files.exists(configFile));
    }

    @Test
    void testWithCustomCleanup(@TempDir(cleanup = CleanupMode.NEVER) Path persistentDir) throws Exception {
        // Directory won't be cleaned up after test
        Path importantFile = persistentDir.resolve("important.data");
        Files.write(importantFile, "Important data that should persist".getBytes());
        
        System.out.println("Data saved to: " + importantFile.toAbsolutePath());
    }

    @Test
    void testCleanupOnSuccess(@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path conditionalDir) throws Exception {
        // Directory cleaned up only if test passes
        Path debugFile = conditionalDir.resolve("debug.log");
        Files.write(debugFile, "Debug information".getBytes());
        
        // If test fails, debug.log will remain for investigation
        assertTrue(Files.exists(debugFile));
    }

    // Multiple temp directories
    @Test
    void testMultipleTempDirs(@TempDir Path inputDir, @TempDir Path outputDir) throws Exception {
        // Create input file
        Path input = inputDir.resolve("input.txt");
        Files.write(input, "Input data".getBytes());
        
        // Process and create output file
        Path output = outputDir.resolve("output.txt");
        String processed = Files.readString(input).toUpperCase();
        Files.write(output, processed.getBytes());
        
        assertEquals("INPUT DATA", Files.readString(output));
    }
}

// Custom temp directory factory
class CustomTempDirectoryTest {
    
    public static class CustomTempDirFactory implements TempDirFactory {
        @Override
        public java.nio.file.Path createTempDirectory(java.lang.reflect.AnnotatedElement annotatedElement, ExtensionContext extensionContext) throws Exception {
            // Create temp directory in specific location with custom naming
            java.nio.file.Path baseDir = java.nio.file.Paths.get(System.getProperty("user.home"), "test-temp");
            java.nio.file.Files.createDirectories(baseDir);
            
            String dirName = "test-" + extensionContext.getDisplayName().replaceAll("[^a-zA-Z0-9]", "-") + "-" + System.currentTimeMillis();
            return java.nio.file.Files.createDirectory(baseDir.resolve(dirName));
        }
    }
    
    @Test
    void testWithCustomFactory(@TempDir(factory = CustomTempDirFactory.class) Path customTempDir) throws Exception {
        // Uses custom factory for directory creation
        assertTrue(customTempDir.toAbsolutePath().toString().contains("test-temp"));
        
        Path testFile = customTempDir.resolve("custom-test.txt");
        Files.write(testFile, "Custom temp directory test".getBytes());
        assertTrue(Files.exists(testFile));
    }
}

Timeout Support

Control test execution timeouts at method and class levels.

import java.util.concurrent.TimeUnit;

/**
 * Set timeout for test execution
 */
@Timeout(
    long value,
    TimeUnit unit = TimeUnit.SECONDS,
    ThreadMode threadMode = ThreadMode.INFERRED
)

/**
 * Thread mode for timeout handling
 */
enum ThreadMode {
    /**
     * Infer thread mode based on execution mode
     */
    INFERRED,
    
    /**
     * Interrupt test execution in same thread
     */
    SAME_THREAD,
    
    /**
     * Execute test in separate thread for timeout
     */
    SEPARATE_THREAD
}

Usage Examples:

import org.junit.jupiter.api.Timeout;
import java.util.concurrent.TimeUnit;

class TimeoutTest {

    @Test
    @Timeout(5) // 5 seconds default
    void fastTest() {
        // Must complete within 5 seconds
        performQuickOperation();
    }

    @Test
    @Timeout(value = 500, unit = TimeUnit.MILLISECONDS)
    void veryFastTest() {
        // Must complete within 500 milliseconds
        int result = 2 + 2;
        assertEquals(4, result);
    }

    @Test
    @Timeout(value = 30, unit = TimeUnit.SECONDS, threadMode = ThreadMode.SEPARATE_THREAD)
    void longRunningTest() {
        // Runs in separate thread, interrupted after 30 seconds
        performLongRunningOperation();
    }

    @Test
    @Timeout(value = 1, unit = TimeUnit.MINUTES)
    void integrationTest() {
        // Integration test with 1 minute timeout
        performIntegrationTest();
    }
}

// Class-level timeout applies to all test methods
@Timeout(10)
class TimedTestClass {
    
    @Test
    void test1() {
        // Inherits 10 second timeout from class
    }
    
    @Test
    @Timeout(30) // Overrides class-level timeout
    void slowTest() {
        // Gets 30 second timeout instead of class default
    }
}

Thread Interruption Handling

Extensions can register callbacks for thread interruption events.

/**
 * Called before a thread is interrupted due to timeout
 */
interface PreInterruptCallback extends Extension {
    void preInterrupt(ExtensionContext context, Thread thread) throws Exception;
}

Usage Examples:

// Extension to handle cleanup before thread interruption
public class CleanupBeforeInterruptExtension implements PreInterruptCallback {
    
    @Override
    public void preInterrupt(ExtensionContext context, Thread thread) throws Exception {
        System.out.println("Test about to be interrupted: " + context.getDisplayName());
        
        // Perform cleanup before interruption
        cleanup();
        
        // Set flag to allow graceful shutdown
        TestState.setInterrupting(true);
    }
    
    private void cleanup() {
        // Close resources, save state, etc.
        ResourceManager.closeAll();
    }
}

@ExtendWith(CleanupBeforeInterruptExtension.class)
class InterruptibleTest {
    
    @Test
    @Timeout(5)
    void longRunningTest() {
        while (!TestState.isInterrupting()) {
            // Check interruption flag periodically
            performWork();
            
            if (Thread.currentThread().isInterrupted()) {
                break;
            }
        }
    }
}

Configuration

Parallel execution is configured through JUnit Platform configuration properties.

Usage Examples:

# Enable parallel execution
junit.jupiter.execution.parallel.enabled=true

# Execution mode strategy
junit.jupiter.execution.parallel.mode.default=concurrent
junit.jupiter.execution.parallel.mode.classes.default=concurrent

# Thread pool configuration
junit.jupiter.execution.parallel.config.strategy=dynamic
junit.jupiter.execution.parallel.config.dynamic.factor=1.0

# Custom thread pool
junit.jupiter.execution.parallel.config.strategy=custom
junit.jupiter.execution.parallel.config.custom.class=com.example.CustomParallelExecutionConfigurationStrategy
// Programmatic configuration
@ExtendWith(ParallelConfigExtension.class)
class ConfiguredParallelTest {
    // Tests with custom parallel configuration
}

public class ParallelConfigExtension implements BeforeAllCallback {
    @Override
    public void beforeAll(ExtensionContext context) throws Exception {
        // Configure parallel execution programmatically
        System.setProperty("junit.jupiter.execution.parallel.enabled", "true");
        System.setProperty("junit.jupiter.execution.parallel.mode.default", "concurrent");
    }
}

Types

Resource Lock

/**
 * Represents a resource lock for synchronization
 */
class Lock {
    Lock(String key, ResourceAccessMode mode);
    
    String getKey();
    ResourceAccessMode getMode();
}

Execution Configuration

/**
 * Strategy interface for parallel execution configuration
 */
interface ParallelExecutionConfigurationStrategy {
    ParallelExecutionConfiguration createConfiguration(ConfigurationParameters configurationParameters);
}

/**
 * Configuration for parallel execution
 */
interface ParallelExecutionConfiguration {
    int getParallelism();
    int getMinimumRunnable();
    int getMaxPoolSize();
    int getCorePoolSize();
    long getKeepAliveTime();
    java.util.concurrent.TimeUnit getKeepAliveTimeUnit();
}

Test Resource Management

/**
 * Interface for closeable test resources that are automatically cleaned up
 */
@FunctionalInterface
interface CloseableResource {
    void close() throws Exception;
}

/**
 * Resource management through extension context
 */
interface Store {
    /**
     * Store a closeable resource that will be automatically closed
     */
    void put(Object key, CloseableResource resource);
}

Usage Examples:

public class DatabaseTestExtension implements BeforeEachCallback, AfterEachCallback {
    
    private static final Namespace NAMESPACE = Namespace.create("database");
    
    @Override
    public void beforeEach(ExtensionContext context) throws Exception {
        // Store closeable resource
        DatabaseConnection connection = new DatabaseConnection();
        context.getStore(NAMESPACE).put("connection", connection::close);
        context.getStore(NAMESPACE).put("connectionObject", connection);
    }
    
    // AfterEachCallback not needed - resources auto-closed by JUnit
}

Install with Tessl CLI

npx tessl i tessl/maven-org-junit-jupiter--junit-jupiter-api

docs

conditional-execution.md

core-testing.md

extension-framework.md

index.md

parallel-io.md

tile.json