A couple of months ago I blogged about JUnit Rules, one of the new features in JUnit. While fooling around with JUnit Rules, I found a couple more features that you might be interested in. So here it comes: Theories! It turns out Theories are really a piece of cake. Try this:

import static org.junit.Assume.assumeTrue;
import org.junit.experimental.theories.DataPoint;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;

@RunWith(Theories.class)
public class TheorieTest {

@DataPoint
public static String a = "a";

@DataPoint
public static String b = "bb";

@DataPoint
public static String c = "ccc";

@Theory
public void stringTest(String x, String y) {
assumeTrue(x.length() > 1);

System.out.println(x + " " + y);
}
}


When you run this you'll get this as an output (and one successfull test):

bb a
bb bb
bb ccc
ccc a
ccc bb
ccc ccc

So what is going on? The first thing to note is that this test is executed by a specialized runner of type Theories. This runner executes all the public methods annotated with @Theory. Differently from normal tests theories have parameters. In order to fill these parameters with values, the Theories runner uses all the public fields of matching Type and annotated with @DataPoint. When you take a look at the output, it should be obvious why this is more powerful then parameterized Tests: Every combination of values is tried, thus with e.g. 4 parameters with 4 distinct values each, you end up with 256 test runs.

The idea is to specify a theory about the object under test, that holds for a large class of states and parameters.  Then you provide those as parameters to the test method which will test the theory.

A probably very common case is that a theory is known not to be valid for certain cases. You can exclude these from a test using the Assume class. If an assumption doesn't hold, the test is silently ignored. This is used in the example above to prevent 'a' to be used as a first parameter.

There are some more tweaks to Theories in JUnit, which I will cover in a later blog. Until then enjoy the new feature. But keep in mind the package in which theories reside up to now: org.junit.experimental.theories so I'd expect some changes in the API and at least a change in package name.