Home Junit 5 Junit 5 conditional test execution with examples

Junit 5 conditional test execution with examples

In this article we will see that what is Junit 5 conditional test execution, and walk through what are the different Conditions that Jupiter api supports with several examples.

JUnit Jupiter api supports several annotation-based conditions in the org.junit.jupiter.api.condition package that allow developers to enable or disable containers and tests declaratively. The simplest example of such a condition is the built-in DisabledCondition which supports the @Disabled annotation.

1. Junit 5 conditional test execution

Following are the several Conditions Junit 5 Jupiter api supports to enable or disable test cases.

  1. Operating System Conditions via @EnabledOnOs and @DisabledOnOs annotations.
  2. Java Runtime Environment Conditions via @EnabledOnJre@DisabledOnJre@EnabledForJreRange and @DisabledForJreRange annotations.
  3. System Property Conditions via the @EnabledIfSystemProperty and @DisabledIfSystemProperty annotations.
  4. Environment Variable Conditions via @EnabledIfEnvironmentVariable and @DisabledIfEnvironmentVariable annotations.
  5. Script Based Conditions via the @EnabledIf or @DisabledIf annotation.
  6. Create Custom Condition by using the ExecutionCondition extension API.1.

1. Operating System Conditions

1.1 Enabled or disabled tests based on a particular operating system via @EnabledOnOs and @DisabledOnOs annotations.

public class OperatingSystemConditionalTest {
	
	@Test
	@EnabledOnOs(OS.MAC)
	void runOnlyOnMacOs() {
	    System.out.println("Run the batch job only on MAC OS");
	}

	@Test
	@EnabledOnOs({ OS.LINUX, OS.MAC })
	void runOnlyOnLinuxOrMac() {
		System.out.println("Run the batch job only on LINUX or MAC OS");
	}

	@Test
	@DisabledOnOs(OS.WINDOWS)
	void notRunOnWindows() {
		System.out.println("Not run the batch job on WINDOWS OS");
	}
	
	@Test
	@EnabledOnOs({ OS.WINDOWS })
	void runOnlyOnWindows() {
		System.out.println("Run the batch job only on WINDOWS OS");
	}
	
	@Test
    @DisabledOnOs({OS.AIX, OS.LINUX, OS.SOLARIS})
    void notRunOnAIXorLinuxOrSolaris() {
        System.out.println("Not run the batch job on AIX or LINUX or SOLARIS");
    }
}

2. Java Runtime Environment Conditions

2.1 Enabled or disabled tests based on a particular Java Runtime Environment (JRE) via @EnabledOnJre and  @DisabledOnJre annotations.

2.2. Enabled or disabled tests based on a particular particular range of versions of the JRE via @EnabledForJreRange and @DisabledForJreRange  annotations ( Introduced in Junit 5.6.0 ).

public class JavaRuntimeEnvironmentConditionalTest {
	
	@Test
	@EnabledOnJre(JRE.JAVA_8)
	void runOnlyOnJava8() {
	    System.out.println("Run the compatibility test only on JRE 8");
	}

	@Test
	@EnabledOnJre({JRE.JAVA_13, JRE.JAVA_14})
	void runOnlyOnJava13OrJava14() {
		System.out.println("Run the compatibility test only on JRE 13 and JRE 14");
	}

	@Test
	@DisabledOnJre(JRE.JAVA_13)
	void notRunOnJava13() {
		System.out.println("not run the compatibility test on JRE 13");
	}
	
	@Test
	@EnabledOnJre(JRE.JAVA_11)
	void runOnlyOnJava11() {
		System.out.println("Run the compatibility test only on JRE 11");
	}
	
	@Test
	@DisabledOnJre({JRE.JAVA_10, JRE.JAVA_11})
    void notRunOnJava10andJava11() {
		System.out.println("not Run the compatibility test on JRE 10 and JRE 11");
    }	
}

3. System Property Conditions

3.1 Enabled or disabled tests based on the value of the named from the JVM system property via @EnabledIfSystemProperty and @DisabledIfSystemProperty annotations.

public class SystemPropertiesConditionalTest {
	
	@Disabled
	@Test
	void printSystemProperties() {
		//remove @Disabled to see System properties
		System.getProperties().forEach((key, value) -> System.out.println(key+" - "+value));
	}

	@Test
	@EnabledIfSystemProperty(named = "java.vm.vendor", matches = "Oracle.*")
	void runOnlyOnOracleJDK() {
		System.out.println("Run this only on Oracle JDK");
	}

	@Test
	@EnabledIfSystemProperty(named = "os.arch", matches = ".*32.*")
	void runOnlyOn32bitOS() {
		System.out.println("Run this on only on 32 bit OS");
	}
	
	@Test
	@DisabledIfSystemProperty(named = "os.version", matches = ".*10.*")
	void notRunOnlyOnWindows10() {
		System.out.println("not run this only on windows 10 version");
	}
	
	@Test
	@EnabledIfSystemProperty(named = "os.version", matches = ".*10.*")
	void runOnlyOnWindows10() {
		System.out.println("Run this only on WINDOWS OS 10 version");
	}
}

4. Environment Variable Conditions

4.1. Enabled or disabled tests based on the value of the named attribute via @EnabledIfEnvironmentVariable and @DisabledIfEnvironmentVariable annotations.

public class EnvironmentVariableConditionalTest {
	
	@Disabled
	@Test
	void printSystemProperties() {
		// Remove @Disabled to see environment properties
		System.getenv().forEach((key, value) -> System.out.println(key+" - "+value));
	}

	@Test
	@EnabledIfEnvironmentVariable(named = "COMPUTERNAME", matches = "sysname")
	void runOnlyOnPerticularMachine() {
		System.out.println("Run this only on perticular server");
	}

	@Test
	@DisabledIfEnvironmentVariable(named = "PROCESSOR_ARCHITECTURE", matches = ".*32.*")
	void noRrunOn32bitOS() {
		System.out.println("Not run this on 32 bit OS");
	}
	
	@Test
	@EnabledIfEnvironmentVariable(named = "USERNAME", matches = "username")
	void runOnlyForPerticularUser() {
		System.out.println("run this only for perticular user in system");
	}
}

5. Script Based Conditions (Deprecated since 5.5)

5.1.  @EnabledIf or @DisabledIf annotations are used to Enable or Disable test cases based on script, they are deprecated in 5.5 version. But if you find yourself script-based condition required for your project, you can create your own condition to achieve that by using ExecutionCondition extension.

public class ScriptBasedConditionalTest {
	
	@Disabled
	@DisplayName("Java Nashorn script Test")
	@Test
	void nashornTest(TestInfo testinfo) {
		
		ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
		try {
			// remove @Disabled to Demonstrating how nashorn script works
			Object result1 = engine.eval("2 * 3 == 6");
			
			System.out.println("(2 * 3 == 6) => "+result1);
			
			Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
			bindings.put("systemProperty", System.getProperties());
			bindings.put("junitDisplayName", testinfo.getDisplayName());
			bindings.put("junitTags", testinfo.getTags());
			engine.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
			
			System.out.println("systemProperty.get('os.arch')) => "+engine.eval("systemProperty.get('os.arch')"));
			System.out.println("junitDisplayName => "+engine.eval("junitDisplayName"));
			System.out.println("junitTags => "+engine.eval("junitTags"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// Static JavaScript expression.
	@Test
	@EnabledIf("2 * 3 == 6")
	void runOnlyIfExpressionValueTrue() {
		System.out.println("(2 * 3 == 6) => true");
	}
	
	// Regular expression testing bound system property.
	@Test
	@DisabledIf("/32/.test(systemProperty.get('os.arch'))")
	void notRunOn32bitOS() {
		System.out.println("Not run this on 32 bit OS");
	}
	
	@Test
	@EnabledIf("'admin' == systemEnvironment.get('USERNAME')")
	void runOnlyForSpecificUser() {
		System.out.println("Run this only for specific user");
	}
	
	// Multi-line script, can give custom engine name and custom reason.
	@Test
	@EnabledIf(value = {
            "load('classpath:script/myScript.js')",
            "",
            "myfunction(10) == true"
        },
        engine = "javascript",
        reason = "On {annotation}, with script: {script}, result is: {result}\"")
	void runOnlyOnlyIfValueIsEven() {
		System.out.println("Run this only for Even numbers");
	}
}

6. Create Junit 5 Custom Condition

We can create a custom condition in two ways in Junit 5.

  1. Create custom annotation by using combination of built-in annotations.
  2. Create your own custom annotation be using implementing ExecutionCondition extension.

6.1. Create custom condition annotation

6.1.1. Following code shows you how to create a custom annotation in Junit 5.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Test
@EnabledOnOs({ OS.WINDOWS })
@EnabledIfSystemProperty(named = "os.version", matches = ".*10.*")
@EnabledIfEnvironmentVariable(named = "PROCESSOR_ARCHITECTURE", matches = ".*64.*")
public @interface RunOnlyOn64bitWindows10 {

}

6.1.2. Usage of custom created annotation

public class CustomConditionalTest {

	@RunOnlyOn64bitWindows10
	void runOnlyOn64bitWindows10() {
		System.out.println("Run only this on 64 bit Windows 10 System.");
	}
}

6.2. Create custom condition annotation by implementing ExecutionCondition

6.2.1. Following code shows you how to create your own conditional annotation by using ExecutionCondition extension.

public class MyDisabledIfConditionExtension implements ExecutionCondition {

   private static final ConditionEvaluationResult ENABLED = ConditionEvaluationResult
			    .enabled("@MyCustomDisabledIf is not present");

	/**
	 *  @MyCustomDisabledIf - your own annotation
	 */
	@Override
	public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
		Optional<AnnotatedElement> element = context.getElement();
		Optional<MyCustomDisabledIf> disabled = findAnnotation(element, MyCustomDisabledIf.class);
		ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
		boolean result = false;

		// result = write logic for disable test using your script engine.

       if (result)
          return ConditionEvaluationResult.disabled("@MyDisabledIf is present with valid condition");

		return ENABLED;
	}
}

6.2.2. Example using @MyCustomDisabledIf

public class MyCustomConditionalTest {
	
	
	@MyCustomDisabledIf("'sysUsername' == systemEnvironment.get('USERNAME')")
	void notRunForSpecificUser() {
		System.out.println("not run this for specific user");
	}
	
	@MyCustomEnabledIf("/64/.test(systemProperty.get('os.arch'))")
	void runOnlyOn64bitMachine() {
		System.out.println("Run this only 64bit System");
	}

}

Conclusion

In this article we have seen that what is Junit 5 conditional test execution, and walked through what are the different Conditions that Jupiter api supports with several examples.

You also might be interested in following examples :

  1. Junit 5 Dynamic Tests and @TestFactory annotation.
  2. Junit 5 tags and filter test cases for execution.
  3. Junit 5 Timeout tests, fail tests if not completed within time.
  4. Junit 5 Repeated tests and display Repetition info.
  5. Junit 5 parameterized tests with different argument sources.
  6. Junit 5 Disable tests using @Disabled annotation

2 COMMENTS

  1. ExecutionCondition example you gave does not a any sense. You define a disable but where are you using it. Where is your MyCustomDisabledIf defined and how you use it on the test.

LEAVE A REPLY

Please enter your comment!
Please enter your name here