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 static org.junit.Assume.assumeTrue;
  1. import org.junit.experimental.theories.DataPoint;
  2. import org.junit.experimental.theories.Theories;
  3. import org.junit.experimental.theories.Theory;
  4. import org.junit.runner.RunWith;
  5.  
  6. @RunWith(Theories.class)
  7. public class TheorieTest {
  8.  
  9.  @DataPoint
  10.  public static String a = "a";
  11.  
  12.  @DataPoint
  13.  public static String b = "bb";
  14.  
  15.  @DataPoint
  16.  public static String c = "ccc";
  17.  
  18.  @Theory
  19.  public void stringTest(String x, String y) {
  20.   assumeTrue(x.length() > 1);
  21.  
  22.   System.out.println(x + " " + y);
  23.  }
  24. }

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.

Share:
  • DZone
  • Digg
  • del.icio.us
  • Reddit
  • Facebook
  • Twitter