Appearance
Conditional Testing
When running tests, sometimes we need to exclude certain @Test
methods from execution. In such cases, we can mark them with @Disabled
:
java
@Disabled
@Test
void testBug101() {
// This test will not run
}
Why not simply comment out the @Test
annotation? By commenting it out, JUnit won't recognize it as a test method. However, by adding @Disabled
, JUnit still identifies it as a test method but temporarily skips its execution. It will appear in the test results as:
Tests run: 68, Failures: 2, Errors: 0, Skipped: 5
Annotations like @Disabled
are known as Conditional Tests. JUnit uses various conditional annotations to decide whether to run the current @Test
method based on different conditions.
Example
Let's look at an example:
java
public class Config {
public String getConfigFile(String filename) {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
return "C:\\" + filename;
}
if (os.contains("mac") || os.contains("linux") || os.contains("unix")) {
return "/usr/local/" + filename;
}
throw new UnsupportedOperationException();
}
}
We want to test the getConfigFile()
method. However, the code paths differ between Windows and Linux/Mac systems. Therefore, we create two test methods: one that runs only on Windows and another that runs only on Mac/Linux.
java
@Test
void testWindows() {
assertEquals("C:\\test.ini", config.getConfigFile("test.ini"));
}
@Test
void testLinuxAndMac() {
assertEquals("/usr/local/test.cfg", config.getConfigFile("test.cfg"));
}
To apply conditions, we add the following annotations to the test methods:
java
@Test
@EnabledOnOs(OS.WINDOWS)
void testWindows() {
assertEquals("C:\\test.ini", config.getConfigFile("test.ini"));
}
@Test
@EnabledOnOs({ OS.LINUX, OS.MAC })
void testLinuxAndMac() {
assertEquals("/usr/local/test.cfg", config.getConfigFile("test.cfg"));
}
@EnabledOnOs
is a conditional test annotation that determines whether a test should run based on the operating system.
Common Conditional Test Annotations
Here are some commonly used conditional test annotations:
Skip Tests on Windows: Use
@DisabledOnOs(OS.WINDOWS)
to exclude tests from running on Windows platforms.java@Test @DisabledOnOs(OS.WINDOWS) void testOnNonWindowsOs() { // TODO: this test is disabled on Windows }
Skip Tests on Specific Java Versions: Use
@DisabledOnJre(JRE.JAVA_8)
to exclude tests from running on Java 8.java@Test @DisabledOnJre(JRE.JAVA_8) void testOnJava9OrAbove() { // TODO: this test is disabled on Java 8 }
Run Tests Only on 64-bit Systems: Use
@EnabledIfSystemProperty
to conditionally run tests based on system properties.java@Test @EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*") void testOnlyOn64bitSystem() { // TODO: this test is only run on 64-bit systems }
Run Tests Based on Environment Variables: Use
@EnabledIfEnvironmentVariable
to run tests only when certain environment variables are set.java@Test @EnabledIfEnvironmentVariable(named = "DEBUG", matches = "true") void testOnlyOnDebugMode() { // TODO: this test is only run when DEBUG=true }
When running all tests in JUnit, the results will indicate which tests were skipped. In IDEs, skipped tests are usually marked with a ⊘ symbol.
Summary
Conditional testing allows JUnit to automatically skip certain tests based on specific annotations and conditions:
- Conditional Tests: Use annotations like
@Disabled
,@EnabledOnOs
,@DisabledOnJre
,@EnabledIfSystemProperty
, and@EnabledIfEnvironmentVariable
to control the execution of test methods based on various criteria. - Visibility in Test Results: Skipped tests are clearly indicated in the test results, helping developers understand which tests were not executed and why.
By leveraging conditional testing, you can create more flexible and environment-specific test suites, ensuring that tests run only when appropriate and reducing unnecessary test executions.