The concept of the test runner is also present in JUnit 4, but it was slightly improved with respect to JUnit 3. In JUnit 4, a test runner is a Java class used to manage a test’s life cycle: instantiation, calling setup and teardown methods, running the test, handling exceptions, sending notifications, and so on. The default JUnit 4 test runner is called BlockJUnit4ClassRunner, and it implements the JUnit 4 standard test case class model.
The test runner to be used in a JUnit 4 test case can be changed simply using the annotation @RunWith. JUnit 4 provides a collection of built-in test runners that allows to change the nature of the test class. In this section, we are going to review the most important ones.
- To run a group of tests (that is, a test suite) JUnit 4 provides the Suite runner. In addition to the runner, the class Suite.SuiteClasses allows to define the individual test classes belonging to the suite. For example:
 
     package io.github.bonigarcia;
     import org.junit.runner.RunWith;
     import org.junit.runners.Suite;
     @RunWith(Suite.class)
     @Suite.SuiteClasses({ TestMinimal1.class, TestMinimal2.class })
     public class MySuite {
     }
- Parameterized tests are used to specify different input data that is going to be used in the same test logic. To implement this kind of tests, JUnit 4 provides the Parameterized runner. To define the data parameters in this type of test, we need to annotate a static method of the class with the annotation @Parameters. This method should return a Collection of the two-dimensional array providing input parameters for the test. Now, there will be two options to inject the input data into the test:
- Using the constructor class.
 
- Annotating class attributes with the annotation @Parameter.
 
 
The following snippets show an example of the latter:
package io.github.bonigarcia;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class TestParameterized {
    @Parameter(0)
    public int input1;
    @Parameter(1)
    public int input2;
    @Parameter(2)
    public int sum;
    @Parameters(name = "{index}: input1={0} input2={1} sum={2}?")
    public static Collection<Object[]> data() {
        return Arrays.asList(
                new Object[][] { { 1, 1, 2 }, { 2, 2, 4 }, { 3, 3, 9 } });
    }
    @Test
    public void testSum() {
        assertTrue(input1 + "+" + input2 + " is not " + sum,
                input1 + input2 == sum);
    }
}
The execution of this test on Eclipse would be as follows:
Execution of a Parameterized test in Eclipse
- JUnit theories are an alternative to JUnit's parameterized tests. A JUnit theory is expected to be true for all datasets. Thus, in JUnit theories, we have a method providing data points (that is, the input values to be used for the test). Then, we need to specific a method annotated with @Theory which takes parameters. The theories in a class get executed with every possible combination of data points:
 
     package io.github.bonigarcia;
     import static org.junit.Assert.assertTrue;
     import org.junit.experimental.theories.DataPoints;
     import org.junit.experimental.theories.Theories;
     import org.junit.experimental.theories.Theory;
     import org.junit.runner.RunWith;
      @RunWith(Theories.class)
     public class MyTheoryTest {
         @DataPoints
         public static int[] positiveIntegers() {
             return new int[] { 1, 10, 100 };
         }
         @Theory
         public void testSum(int a, int b) {
             System.out.println("Checking " + a + "+" + b);
             assertTrue(a + b > a);
             assertTrue(a + b > b);
         }
     }
Take a look at the execution of this example, again in Eclipse:
Execution of a JUnit 4 theory in Eclipse