Thursday, 3 January 2013

JUnit4 - Parameterization

Junit 4 has introduced a new feature called Parameterization.  Parameterized tests allow the developers to run the same test over and over again using different values. There are 5 different steps that you need to followup in-order to create Parameterized tests.
  1. Annotating the test class with @RunWith(Parameterized.class)
  2. Create a public static method annotated with @Parameters that returns a Collection of Objects (as Array) as test data set.
  3. Create a public constructor that takes in what is equivalent to one "row" of test data.
  4. Create an instance variable for each "column" of test data.
  5. Create your tests case(s) using the instance variables as the source of the test data.
The test case will be invoked once per each row of data. Let's see Parameterized tests in action.

Exercise |1|

1| Create a java class; say, Calculator.java

public class Calculator {
public int add(int x, int y){
return x+y;
}
}

Create Parameterized Test Class

2| Create a java test class say, Easy.java

import java.util.Arrays;
import java.util.Collection;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class Easy {

private int Expected;
private int Firstval;
private int Secondval;
public Calculator cal;

@Before
public void setUp(){
cal = new Calculator();
}

public Easy(int Expected, int Firstval, int Secondval){
this.Expected = Expected;
this.Firstval = Firstval;
this.Secondval = Secondval;
}

@Parameters
public static Collection<Object[]> storedtestdata(){
return Arrays.asList(new Object[][]{
{5,3,2}, // pass
{8,4,4}, // pass
{6,1,4}  // fail
});
}

@Test
public void Test01(){
Assert.assertEquals(Expected, cal.add(Firstval, Secondval));
}
}

Create Test Runner Class [Optional and not mandatory]

3| Create a class, TestRunner.java under the same package in-order to execute Test case(s)

import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(Easy.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
}  
Verify the output:

Test01[2](pack.Easy): expected:<6> but was:<5>
false


Exercise |2|

1| Create a java class; say, PrimeNumberChecker.java

public class PrimeNumberChecker {
   public Boolean validate(final Integer primeNumber) {
      for (int i = 2; i < (primeNumber / 2); i++) {
         if (primeNumber % i == 0) {
            return false;
         }
      }
      return true;
   }
}

Create Parameterized Test Class

2| Create a java class; say, PrimeNumberCheckerTest.java

@RunWith(Parameterized.class)
public class PrimeNumberCheckerTest {
   private Integer inputNumber;
   private Boolean expectedResult;
   private PrimeNumberChecker primeNumberChecker;

   @Before
   public void initialize() {
      primeNumberChecker = new PrimeNumberChecker();
   }

   // Each parameter should be placed as an argument here
   // Every time runner triggers, it will pass the arguments
   // from parameters we defined in primeNumbers() method
   public PrimeNumberCheckerTest(Integer inputNumber, 
      Boolean expectedResult) {
      this.inputNumber = inputNumber;
      this.expectedResult = expectedResult;
   }

   @Parameterized.Parameters
   public static Collection primeNumbers() {
      return Arrays.asList(new Object[][] {
         { 2, true },
         { 6, false },
         { 19, true },
         { 22, false },
         { 23, true }
      });
   }

   // This test will run 4 times since we have 5 parameters defined
   @Test
   public void testPrimeNumberChecker() {
      System.out.println("Parameterized Number is : " + inputNumber);
      assertEquals(expectedResult, 
      primeNumberChecker.validate(inputNumber));
   }
}
Verify the output:

Parameterized Number is : 2
Parameterized Number is : 6
Parameterized Number is : 19
Parameterized Number is : 22
Parameterized Number is : 23
true

2 comments: