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

conditional-execution.mddocs/

Conditional Test Execution

Runtime environment-based test control for platform-specific, JRE-specific, and custom conditional testing scenarios. These annotations allow tests to be enabled or disabled based on operating system, Java version, system properties, environment variables, or custom conditions.

Capabilities

Operating System Conditions

Enable or disable tests based on the current operating system and architecture.

/**
 * Enable test only on specified operating systems
 */
@EnabledOnOs(OS value)
@EnabledOnOs(OS[] value)
@EnabledOnOs(value = OS.LINUX, architectures = "aarch64")
@EnabledOnOs(value = {OS.LINUX, OS.MAC}, disabledReason = "Not supported on Windows")

/**
 * Disable test on specified operating systems
 */
@DisabledOnOs(OS value)
@DisabledOnOs(OS[] value)
@DisabledOnOs(value = OS.WINDOWS, architectures = {"x86_64", "amd64"})

/**
 * Operating system enumeration
 */
enum OS {
    AIX, FREEBSD, LINUX, MAC, OPENBSD, SOLARIS, WINDOWS, OTHER;
    
    /**
     * Get the current operating system
     */
    static OS current();
    
    /**
     * Check if this OS matches the current system
     */
    boolean isCurrentOs();
}

Usage Examples:

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

class PlatformSpecificTest {

    @Test
    @EnabledOnOs(OS.LINUX)
    void linuxOnlyTest() {
        // This test only runs on Linux
        assertTrue(System.getProperty("os.name").toLowerCase().contains("linux"));
    }

    @Test
    @DisabledOnOs({OS.WINDOWS, OS.MAC})
    void notOnWindowsOrMac() {
        // Runs on all systems except Windows and Mac
        ProcessBuilder pb = new ProcessBuilder("ps", "-ef");
        assertDoesNotThrow(() -> pb.start());
    }

    @Test
    @EnabledOnOs(value = OS.LINUX, architectures = "aarch64")
    void linuxArm64Only() {
        // Only runs on ARM64 Linux systems
        assertEquals("aarch64", System.getProperty("os.arch"));
    }

    @Test
    @DisabledOnOs(value = OS.WINDOWS, disabledReason = "File permissions work differently on Windows")
    void unixFilePermissions() {
        // Test Unix-specific file permission behavior
        Path file = Files.createFile(tempDir.resolve("test.txt"));
        Files.setPosixFilePermissions(file, PosixFilePermissions.fromString("rwxr--r--"));
    }
}

Java Runtime Environment Conditions

Enable or disable tests based on JRE version.

/**
 * Enable test only on specified JRE versions
 */
@EnabledOnJre(JRE value)
@EnabledOnJre(JRE[] value)

/**
 * Disable test on specified JRE versions
 */
@DisabledOnJre(JRE value)
@DisabledOnJre(JRE[] value)

/**
 * Enable test for a range of JRE versions
 */
@EnabledForJreRange(JRE min = JRE.JAVA_8, JRE max = JRE.JAVA_17)

/**
 * Disable test for a range of JRE versions
 */
@DisabledForJreRange(JRE min = JRE.JAVA_8, JRE max = JRE.JAVA_11)

/**
 * Java Runtime Environment version enumeration
 */
enum JRE {
    JAVA_8, JAVA_9, JAVA_10, JAVA_11, JAVA_12, JAVA_13, JAVA_14, 
    JAVA_15, JAVA_16, JAVA_17, JAVA_18, JAVA_19, JAVA_20, JAVA_21, OTHER;
    
    /**
     * Get the current JRE version
     */
    static JRE current();
    
    /**
     * Check if this JRE version matches the current runtime
     */
    boolean isCurrentVersion();
}

Usage Examples:

class JreSpecificTest {

    @Test
    @EnabledOnJre(JRE.JAVA_11)
    void java11OnlyFeature() {
        // Test features specific to Java 11
        String result = "hello world".repeat(3);
        assertEquals("hello worldhello worldhello world", result);
    }

    @Test
    @DisabledOnJre({JRE.JAVA_8, JRE.JAVA_9})
    void modernJavaFeatures() {
        // Uses features not available in Java 8/9
        var list = List.of("item1", "item2", "item3");
        assertTrue(list.size() > 0);
    }

    @Test
    @EnabledForJreRange(min = JRE.JAVA_11, max = JRE.JAVA_17)
    void supportedJavaVersions() {
        // Test runs on Java 11 through 17
        assertDoesNotThrow(() -> {
            // Use features available in this range
            String text = """
                Multi-line
                string literal
                """;
            assertFalse(text.isEmpty());
        });
    }

    @Test
    @DisabledForJreRange(min = JRE.JAVA_8, max = JRE.JAVA_10, disabledReason = "Module system required")
    void moduleSystemFeatures() {
        // Test module system features not available before Java 11
        Module module = getClass().getModule();
        assertNotNull(module);
    }
}

System Property Conditions

Enable or disable tests based on system properties.

/**
 * Enable test if system property matches condition
 */
@EnabledIfSystemProperty(named = "property.name", matches = "regex")

/**
 * Disable test if system property matches condition
 */
@DisabledIfSystemProperty(named = "property.name", matches = "regex")

/**
 * Multiple system property conditions (all must be true)
 */
@EnabledIfSystemProperties({
    @EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*"),
    @EnabledIfSystemProperty(named = "java.vendor", matches = ".*OpenJDK.*")
})

@DisabledIfSystemProperties({
    @DisabledIfSystemProperty(named = "env.type", matches = "production"),
    @DisabledIfSystemProperty(named = "skip.integration", matches = "true")
})

Usage Examples:

class SystemPropertyTest {

    @Test
    @EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*")
    void on64BitArchitecture() {
        // Only runs on 64-bit architectures
        String arch = System.getProperty("os.arch");
        assertTrue(arch.contains("64"));
    }

    @Test
    @DisabledIfSystemProperty(named = "headless", matches = "true")
    void guiTest() {
        // Skipped in headless environments
        assertFalse(GraphicsEnvironment.isHeadless());
        // GUI testing code here
    }

    @Test
    @EnabledIfSystemProperties({
        @EnabledIfSystemProperty(named = "test.environment", matches = "integration"),
        @EnabledIfSystemProperty(named = "database.url", matches = ".*localhost.*")
    })
    void integrationTestWithLocalDatabase() {
        // Only runs if both conditions are met
        assertEquals("integration", System.getProperty("test.environment"));
        assertTrue(System.getProperty("database.url").contains("localhost"));
    }

    @Test
    @DisabledIfSystemProperty(named = "skip.slow.tests", matches = "true", disabledReason = "Slow tests disabled")
    void slowIntegrationTest() {
        // Skip when -Dskip.slow.tests=true is set
        Thread.sleep(5000); // Simulate slow test
    }
}

Environment Variable Conditions

Enable or disable tests based on environment variables.

/**
 * Enable test if environment variable matches condition
 */
@EnabledIfEnvironmentVariable(named = "ENV_VAR", matches = "regex")

/**
 * Disable test if environment variable matches condition
 */
@DisabledIfEnvironmentVariable(named = "ENV_VAR", matches = "regex")

/**
 * Multiple environment variable conditions (all must be true)
 */
@EnabledIfEnvironmentVariables({
    @EnabledIfEnvironmentVariable(named = "CI", matches = "true"),
    @EnabledIfEnvironmentVariable(named = "BUILD_ENV", matches = "staging|production")
})

@DisabledIfEnvironmentVariables({
    @DisabledIfEnvironmentVariable(named = "SKIP_TESTS", matches = ".*integration.*"),
    @DisabledIfEnvironmentVariable(named = "LIGHTWEIGHT_BUILD", matches = "true")
})

Usage Examples:

class EnvironmentVariableTest {

    @Test
    @EnabledIfEnvironmentVariable(named = "CI", matches = "true")
    void continuousIntegrationTest() {
        // Only runs in CI environments
        assertEquals("true", System.getenv("CI"));
        // CI-specific test logic
    }

    @Test
    @DisabledIfEnvironmentVariable(named = "SKIP_DOCKER_TESTS", matches = "true")
    void dockerContainerTest() {
        // Skipped when SKIP_DOCKER_TESTS=true
        // Docker-based integration test
        DockerClient client = DockerClient.getInstance();
        assertNotNull(client);
    }

    @Test
    @EnabledIfEnvironmentVariables({
        @EnabledIfEnvironmentVariable(named = "AWS_REGION", matches = "us-.*"),
        @EnabledIfEnvironmentVariable(named = "AWS_ACCESS_KEY_ID", matches = ".+")
    })
    void awsIntegrationTest() {
        // Only runs with proper AWS configuration in US regions
        String region = System.getenv("AWS_REGION");
        assertTrue(region.startsWith("us-"));
        assertNotNull(System.getenv("AWS_ACCESS_KEY_ID"));
    }

    @Test
    @DisabledIfEnvironmentVariable(named = "BUILD_ENV", matches = "production", disabledReason = "Not safe in production")
    void destructiveTest() {
        // Never runs in production environment
        // Potentially destructive test operations
    }
}

Custom Method Conditions

Enable or disable tests based on custom condition methods.

/**
 * Enable test if method returns true
 */
@EnabledIf("methodName")
@EnabledIf(value = "methodName", disabledReason = "Custom condition not met")

/**
 * Disable test if method returns true
 */
@DisabledIf("methodName")
@DisabledIf(value = "methodName", disabledReason = "Custom condition prevents execution")

Usage Examples:

class CustomConditionTest {

    @Test
    @EnabledIf("isDatabaseAvailable")
    void databaseTest() {
        // Only runs if database is available
        assertTrue(isDatabaseAvailable());
        // Database test logic
    }

    @Test
    @DisabledIf("isProductionEnvironment")
    void developmentOnlyTest() {
        // Skipped in production
        assertFalse(isProductionEnvironment());
        // Development/testing specific code
    }

    @Test
    @EnabledIf(value = "hasRequiredFeature", disabledReason = "Required feature not available")
    void featureSpecificTest() {
        // Only runs if specific feature is available
        assertTrue(hasRequiredFeature());
        // Feature-specific test logic
    }

    // Condition methods must be static and return boolean
    static boolean isDatabaseAvailable() {
        try {
            java.sql.Connection conn = java.sql.DriverManager.getConnection("jdbc:h2:mem:test");
            conn.close();
            return true;
        } catch (java.sql.SQLException e) {
            return false;
        }
    }

    static boolean isProductionEnvironment() {
        return "production".equals(System.getenv("ENV"));
    }

    static boolean hasRequiredFeature() {
        return System.getProperty("features", "").contains("advanced");
    }
}

Native Image Conditions

Enable or disable tests when running in GraalVM native image.

/**
 * Enable test only when running in a native image
 */
@EnabledInNativeImage

/**
 * Disable test when running in a native image
 */
@DisabledInNativeImage

Usage Examples:

class NativeImageTest {

    @Test
    @EnabledInNativeImage
    void nativeImageOnlyTest() {
        // Only runs in GraalVM native image
        // Test native image specific behavior
        assertTrue(isNativeImage());
    }

    @Test
    @DisabledInNativeImage
    void jvmOnlyTest() {
        // Skipped in native image, uses reflection heavily
        Class<?> clazz = SomeClass.class;
        Method[] methods = clazz.getDeclaredMethods();
        assertTrue(methods.length > 0);
    }

    private boolean isNativeImage() {
        return System.getProperty("org.graalvm.nativeimage.imagecode") != null;
    }
}

Combining Conditions

Multiple conditional annotations can be combined on the same test method.

Usage Examples:

class CombinedConditionsTest {

    @Test
    @EnabledOnOs(OS.LINUX)
    @EnabledForJreRange(min = JRE.JAVA_11)
    @EnabledIfEnvironmentVariable(named = "CI", matches = "true")
    void linuxJava11CiTest() {
        // Only runs on Linux, Java 11+, in CI environment
        // All conditions must be satisfied
    }

    @Test
    @DisabledOnOs(OS.WINDOWS)
    @DisabledIfSystemProperty(named = "headless", matches = "true")
    @DisabledIf("isResourceConstrained")
    void resourceIntensiveTest() {
        // Skipped if ANY condition is met:
        // - Running on Windows, OR
        // - In headless mode, OR  
        // - System is resource constrained
    }

    static boolean isResourceConstrained() {
        Runtime runtime = Runtime.getRuntime();
        return runtime.maxMemory() < 1024 * 1024 * 1024; // Less than 1GB
    }
}

Error Handling

When conditional annotations are misconfigured or condition methods throw exceptions, JUnit will report the error and typically disable the affected test.

@Test
@EnabledIf("nonExistentMethod") // Error: method not found
void misconfiguredTest() {
    // This test will be disabled due to configuration error
}

@Test  
@EnabledIf("throwingConditionMethod")
void testWithThrowingCondition() {
    // This test will be disabled if condition method throws exception
}

static boolean throwingConditionMethod() {
    throw new RuntimeException("Condition evaluation failed");
}

Types

Condition Evaluation Result

/**
 * Result of evaluating an execution condition
 */
class ConditionEvaluationResult {
    static ConditionEvaluationResult enabled(String reason);
    static ConditionEvaluationResult disabled(String reason);
    
    boolean isDisabled();
    Optional<String> getReason();
}

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