New Feature of JUnit: Theories
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 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.






Very cool feature – I hope this makes it to their core soon. Thanks for the post.
[...] Dieser Eintrag wurde auf Twitter von Richard Laksana, Jens Schauder, seanparsons, Peter Backx, pembleton und anderen erwähnt. pembleton sagte: Reading "New Feature of JUnit: Theories" http://bit.ly/9F25JH by @jensschauder [...]
[...] blog provides a great summary of what theories are and how to write a parameter supplier to supply a series of datapoints in Java. The annotation [...]
[...] New Feature of JUnit: Theories – this looks very interesting [...]
Thank you for this short and simple explanation.
With an example coding sometimes is a piece of cake.
Haiko.
[...] been writing JUnit Parameterized tests (a nice intro here – also see Theories) to do some data driven API testing. Now, when introducing Spring into the mix there are a couple [...]
[...] Schauder wrote an example test where each test method (theory) is executed for all possible 2-element combinations of …. Jacob Childress uses theories as an alternative to Parametrized by using only a single parameter [...]
[...] http://blog.schauderhaft.de/2010/01/31/new-feature-of-junit-theories/ [...]
[...] articles exploring the basics: Mark Needham, Locke’s Socks, Schauderhaft, ig blog, Chris Kelly. Note that these articles don’t tend to follow the ‘test inverse [...]
Any chance the junit.org links are hosted anywhere other than github?
Hi Jeff,
not sure what your intention is.
JUnit is open source and I guess you can take the source code and host it anywhere you want.
Or are any links pointing into the void? This might be because the JUnit repository was migrated from Kent Becks user to the JUnit organization: https://github.com/junit-team/junit
Am I missing something? Why isn’t “a” run with “a”? “bb” is run with “bb” and “ccc” with “ccc”, etc.
Hi Jay,
the line assumeTrue(x.length() > 1); skips the test when x = a because it doesn’t satisfy the condition.