Parameterized Tests

Sometimes you want to use a generic test method to test with different sets of values. But if you use a loop to do that, then the whole method will fail if 1 of the set of values fails. As a result, it is not helpful as you don't know which specific set of values failed. JUnit report will only show that the generic test method as a whole failed. But if you are writing 1 test method per set of values, then there is a lot of codes, which is not efficient and practical.

Fortunately, JUnit has a feature called parameterized test which will replicate the same test method for each set of values. Consequently, if 1 of the set of values fails, JUnit will show you which set failed.

Below is a simple example of a parameterized test.

/**
 * Show how parameterized test is done in JUnit.
 * 1)Put the annotation @RunWith for the Test Class
 * 2)Must have a public static method that returns a Collection of data.
 * 3)You will also need a public constructor that uses the parameters.
 *
 * This parameterized test is intended to fail on the 3rd data set to show you
 *  a mixture of pass and failed data set.
 * @Author: Xuan Ngo
 */
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
 
 
import java.util.Arrays;
import java.util.Collection;
 
@RunWith(Parameterized.class)
public class ParameterizedTest
{
  private int m_iA = 0;
  private int m_iB = 0;
  private int m_iExpected = 0;
 
  // Needs a public static method (here the function name is irrelevant) that
  // returns a Collection and is annotated with @Parameters.
  @Parameters
  public static Collection data()
  {
    return Arrays.asList(new Object[][]
                            {
                              // {iA, iB, iExpected},
                              { 0, 0, 0 }, 
                              { 1, 1, 2 }, 
                              { 2, 4, 5 }, // will fail.
                              { 2, 4, 6 }, });
  }
 
  /*
    // Another way to implement Collection data()    
    @Parameters
    public static ArrayList<Integer[]> data()
    {
      ArrayList<Integer[]> oArrayList = new ArrayList<Integer[]>();
      // {iA, iB, iExpected},
      oArrayList.add(new Integer[]{1,1,2});
      oArrayList.add(new Integer[]{9,5,14});
      oArrayList.add(new Integer[]{5,5,11});
 
      return oArrayList;
    }
  */
 
  // Constructor: Make sure that argument parameters are in the
  // same order as your Collection data.
  public ParameterizedTest(int iA, int iB, int iExpected)
  {
    this.m_iA = iA;
    this.m_iB = iB;
    this.m_iExpected = iExpected;
  }
 
  @Test
  public void TestingExclusivelyGetSum()
  {
    final int iResult = this.getSum(this.m_iA, this.m_iB);
    assertEquals(this.m_iExpected, iResult);
  }
 
  // To test getSum() function, I put it here so
  // that this test class is self completed.
  public int getSum(final int iA, final int iB)
  {
    return iA + iB;
  }
}