2.7. Conditional Test Execution

The ExecutionCondition extension API in JUnit Jupiter allows developers to either enable or disable a container or test based on certain conditions programmatically. The simplest example of such a condition is the built-in [DisabledCondition](https://github.com/junit-team/junit5/tree/r5.7.0/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DisabledCondition.java) which supports the [@Disabled](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/Disabled.html) annotation (see Disabling Tests). In addition to @Disabled, JUnit Jupiter also supports several other annotation-based conditions in the org.junit.jupiter.api.condition package that allow developers to enable or disable containers and tests declaratively. When multiple ExecutionCondition extensions are registered, a container or test is disabled as soon as one of the conditions returns disabled. If you wish to provide details about why they might be disabled, every annotation associated with these built-in conditions has a disabledReason attribute available for that purpose.

See ExecutionCondition and the following sections for details.

Composed Annotations

Note that any of the conditional annotations listed in the following sections may also be used as a meta-annotation in order to create a custom composed annotation. For example, the @TestOnMac annotation in the @EnabledOnOs demo shows how you can combine @Test and @EnabledOnOs in a single, reusable annotation.

Unless otherwise stated, each of the conditional annotations listed in the following sections can only be declared once on a given test interface, test class, or test method. If a conditional annotation is directly present, indirectly present, or meta-present multiple times on a given element, only the first such annotation discovered by JUnit will be used; any additional declarations will be silently ignored. Note, however, that each conditional annotation may be used in conjunction with other conditional annotations in the org.junit.jupiter.api.condition package.

2.7.1. Operating System Conditions

A container or test may be enabled or disabled on a particular operating system via the [@EnabledOnOs](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/EnabledOnOs.html) and [@DisabledOnOs](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/DisabledOnOs.html) annotations.

  1. @Test
  2. @EnabledOnOs(MAC)
  3. void onlyOnMacOs() {
  4. // ...
  5. }
  6. @TestOnMac
  7. void testOnMac() {
  8. // ...
  9. }
  10. @Test
  11. @EnabledOnOs({ LINUX, MAC })
  12. void onLinuxOrMac() {
  13. // ...
  14. }
  15. @Test
  16. @DisabledOnOs(WINDOWS)
  17. void notOnWindows() {
  18. // ...
  19. }
  20. @Target(ElementType.METHOD)
  21. @Retention(RetentionPolicy.RUNTIME)
  22. @Test
  23. @EnabledOnOs(MAC)
  24. @interface TestOnMac {
  25. }

2.7.2. Java Runtime Environment Conditions

A container or test may be enabled or disabled on particular versions of the Java Runtime Environment (JRE) via the [@EnabledOnJre](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/EnabledOnJre.html) and [@DisabledOnJre](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/DisabledOnJre.html) annotations or on a particular range of versions of the JRE via the [@EnabledForJreRange](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/EnabledForJreRange.html) and [@DisabledForJreRange](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/DisabledForJreRange.html) annotations. The range defaults to [JRE](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/JRE.html).JAVA_8 as the lower border (min) and [JRE](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/JRE.html).OTHER as the higher border (max), which allows usage of half open ranges.

  1. @Test
  2. @EnabledOnJre(JAVA_8)
  3. void onlyOnJava8() {
  4. // ...
  5. }
  6. @Test
  7. @EnabledOnJre({ JAVA_9, JAVA_10 })
  8. void onJava9Or10() {
  9. // ...
  10. }
  11. @Test
  12. @EnabledForJreRange(min = JAVA_9, max = JAVA_11)
  13. void fromJava9to11() {
  14. // ...
  15. }
  16. @Test
  17. @EnabledForJreRange(min = JAVA_9)
  18. void fromJava9toCurrentJavaFeatureNumber() {
  19. // ...
  20. }
  21. @Test
  22. @EnabledForJreRange(max = JAVA_11)
  23. void fromJava8To11() {
  24. // ...
  25. }
  26. @Test
  27. @DisabledOnJre(JAVA_9)
  28. void notOnJava9() {
  29. // ...
  30. }
  31. @Test
  32. @DisabledForJreRange(min = JAVA_9, max = JAVA_11)
  33. void notFromJava9to11() {
  34. // ...
  35. }
  36. @Test
  37. @DisabledForJreRange(min = JAVA_9)
  38. void notFromJava9toCurrentJavaFeatureNumber() {
  39. // ...
  40. }
  41. @Test
  42. @DisabledForJreRange(max = JAVA_11)
  43. void notFromJava8to11() {
  44. // ...
  45. }

2.7.3. System Property Conditions

A container or test may be enabled or disabled based on the value of the named JVM system property via the [@EnabledIfSystemProperty](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/EnabledIfSystemProperty.html) and [@DisabledIfSystemProperty](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/DisabledIfSystemProperty.html) annotations. The value supplied via the matches attribute will be interpreted as a regular expression.

  1. @Test
  2. @EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*")
  3. void onlyOn64BitArchitectures() {
  4. // ...
  5. }
  6. @Test
  7. @DisabledIfSystemProperty(named = "ci-server", matches = "true")
  8. void notOnCiServer() {
  9. // ...
  10. }

As of JUnit Jupiter 5.6, @EnabledIfSystemProperty and @DisabledIfSystemProperty are repeatable annotations. Consequently, these annotations may be declared multiple times on a test interface, test class, or test method. Specifically, these annotations will be found if they are directly present, indirectly present, or meta-present on a given element.

2.7.4. Environment Variable Conditions

A container or test may be enabled or disabled based on the value of the named environment variable from the underlying operating system via the [@EnabledIfEnvironmentVariable](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariable.html) and [@DisabledIfEnvironmentVariable](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariable.html) annotations. The value supplied via the matches attribute will be interpreted as a regular expression.

  1. @Test
  2. @EnabledIfEnvironmentVariable(named = "ENV", matches = "staging-server")
  3. void onlyOnStagingServer() {
  4. // ...
  5. }
  6. @Test
  7. @DisabledIfEnvironmentVariable(named = "ENV", matches = ".*development.*")
  8. void notOnDeveloperWorkstation() {
  9. // ...
  10. }

As of JUnit Jupiter 5.6, @EnabledIfEnvironmentVariable and @DisabledIfEnvironmentVariable are repeatable annotations. Consequently, these annotations may be declared multiple times on a test interface, test class, or test method. Specifically, these annotations will be found if they are directly present, indirectly present, or meta-present on a given element.

2.7.5. Custom Conditions

A container or test may be enabled or disabled based on the boolean return of a method via the [@EnabledIf](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/EnabledIf.html) and [@DisabledIf](https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/condition/DisabledIf.html) annotations. The method is provided to the annotation via its name, or its fully qualified name if located outside the test class. If needed, the condition method can take a single parameter of type ExtensionContext.

  1. @Test
  2. @EnabledIf("customCondition")
  3. void enabled() {
  4. // ...
  5. }
  6. @Test
  7. @DisabledIf("customCondition")
  8. void disabled() {
  9. // ...
  10. }
  11. boolean customCondition() {
  12. return true;
  13. }
When @EnabledIf or @DisabledIf is used at class level, the condition method must always be static. Condition methods located in external classes must also be static. In any other case, you can use both static or instance methods.