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.

- Advertisement -

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;
	}
}

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

- Advertisement -
Satish Varma
Satish Varmahttps://javabydeveloper.com
Satish is post graduated in master of computer applications and experienced software engineer with focus on Spring, JPA, REST, TDD and web development. Also founder of javabydeveloper.com. Follow him on LinkedIn or Twitter or Facebook

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Stay in Touch

Categories

Related Articles