Monday, October 13, 2008

A run-time equivalent to JUnit's @Ignore

It's been some time since I wrote about things that annoy me. Now it's time again. The pain-in-the-lower-back this time is: why isn't there a (good) way to ignore a JUnit test-case based on a piece of information that only awailable at run-time? In short: dynamically ignore a test-case.
I think a "good way" to solve this should fulfill the following:
  • a dynamically ignore test-case should marked as "ignored" in the JUnit test-run,
  • possible search for dynamically ignored test-cases in the IDE.

There is a very simple way to ignore a test-case base on run-time information:
@Test
public void testIt() {
  if (shouldIgnore())
    return;
  // ... the rest of the test-case.
}

However, this solution does not fulfill the above requirements at all. Something better is needed.

JUnit uses a org.junit.runner.Runner to run test-cases. Since JUnit 4.0 it's possible to define which such Runner that should be used to run a set of test-cases. The @RunWith annotation does just this. Here is an example:
@RunWith(MyRunner.class)
public final class MyTest {
  // ... some test-cases.
}

There are several ways @RunWith can make you testing filled days easier; for a real-world example you need to look no further than to JMock. I have implemented a Runner that makes it possible to do:
@RunWith(RuntimeIgnoreable.class)
public final class MyTest {
  @Test
  public void perhapsIgnored() {
    ignoreIf(perhapsTrue())
    // ... the rest of the test-case.
  }
}

Neat, ey? I think so at least. What's even neater is that the RuntimeIgnoreable class and the ignoreIf method was embaressingly straight-forward to implement. You can browse the code, or look at the individuals files:

Oh, one final note: this was develop for JUnit 4.3. If you are using any other JUnit version, the you prbably need to make some minor changes to the code.

Update: I just realize that JUnit Extensions does this (among aother things)...

6 comments:

karadoc said...

Can't you just do that with assumptions?
e.g. Assume.assumeTrue(blah)

Torgny said...

As far as I know, a failing assuption does not make the test-case fail in JUnit 4.4; it just interupts the test. So if you are using JUnit 4.4, then what you propose will work fine.

However, if you're using JUnit 4.x (where x != 4 :)), then that won't work. In 4.5 you get AssumptionError (or something like that) when an assuption fails. And, of course, in JUnit 4.3 and earlier versions, there are no assuptions (Assume.assumeXYZ methods).

Unknown said...

Awesome. Works like a charm and does exactly what i wanted to do. I dont agree that you can use the Assume junit feature - I dont want to have to invade the code of my test method, i want to simply have a conditional @Ignore

Perhaps a cleaner syntax would be an annotation like @IgnoreIf(someCondition()==true) but dont have the time to look into it right now, do annotations even support this kind of syntax?

Anyway it works right now and gets me out of a hole so im happy.

We are using Junit 4.4

Unknown said...

Hi,
The links doesn't work anymore. It says: "SVN hosting has been permanently disabled."

Do you mind to share them somewhere else please?

Thanks!

Torgny said...

Hi!
I'll look into this and see what I can do.

Torgny said...

Sorry, It seems like Google Code isn't available anymore. It has been taken offline and isn't even available read-only anymore.