Search code examples
javajunitjunit-rule

How can I automatically skip certain JUnit tests based on a condition?


I would like a simple way to assign a priority value to my JUnit tests such that I can say 'run only priority 1 tests', 'run priority 1, 2 and 3 tests' etc. I am aware that I could just include a line like Assume.assumeTrue("Test skipped for priority " + priority, priority <= 2); at the start of each test (where priority is the highest value priority tests I want to run and 2 is the priority value of this particular test), however copy-pasting a line at the start of each test doesn't seem a very good solution.

I have tried writing a solution using a simple annotation which is detected by the JUnit Rule I am using anyway:

public class Tests {
    @Rule
    public TestRules rules = new TestRules();
    @Test
    @Priority(2)
    public void test1() {
        // perform test
    }
}

public class TestRules extends TestWatcher {
    private int priority = 1; // this value is manually changed to set the priority of tests to run
    @Override
    protected void starting(Description desc) {
        Priority testCasePriority = desc.getAnnotation(Priority.class);
        Assume.assumeTrue("Test skipped for priotity " + priority, testCasePriority == null || testCasePriority.value() <= priority);
    }
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Priority {
    public int value() default 0;
}

While this appears to work (the correct tests are shown as skipped in the Eclipse JUnit view) the tests are still performed, i.e. any code in test1() is still run.

Does anyone have any idea how I can get the Assume in my Rule to actually skip the test?


Solution

  • The exception thrown by a TestWatcher.starting are ignored, and rethrown at the end of the test.

    You should implement a TestRule instead of a TestWatcher :

    public class TestRules implements TestRule {
        private int priority = 1; // this value is manually changed to set the priority of tests to run
    
         public Statement apply(final Statement base, final Description description) {
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    Priority testCasePriority = desc.getAnnotation(Priority.class);
                    Assume.assumeTrue("Test skipped for priotity " + priority, testCasePriority == null || testCasePriority.value() <= priority);
    
                    base.evaluate();
                }
            };
        }
    }