Parameterized Test Runner in JUnit
Join the DZone community and get the full member experience.
Join For FreeWe all have written unit tests where in a single test tests for different possible input-output combinations. Lets look how its done by taking a simple fibonacci series example.
The below code computes the fibonacci series for number of elements mentioned.
import java.math.BigInteger; import java.util.ArrayList; import java.util.List; public class Fibonacci{ public List<Integer> getFiboSeries(int numberOfElements) { List<Integer> fiboSeries = new ArrayList<>(numberOfElements); for (int i = 0; i < numberOfElements; i++) { //First 2 elements are 1,1 if (i == 0 || i == 1) { fiboSeries.add(i, 1); } else { int firstPrev = fiboSeries.get(i - 2); int secondPrev = fiboSeries.get(i - 1); int fiboElement = firstPrev + secondPrev; fiboSeries.add(i, fiboElement); } } return fiboSeries; } }
Lets see the conventional way of testing the above code with multiple input values.
import java.util.List; import org.junit.Test; import java.util.Arrays; import static org.junit.Assert.*; public class FibonacciCachedTest { /** * Test of getFiboSeries method, of class Fibonacci. */ @Test public void testGetFiboSeries() { System.out.println("getFiboSeries"); int numberOfElements = 5; Fibonacci instance = new Fibonacci(); List<Integer> expResult = Arrays.asList(1, 1, 2, 3, 5); List<Integer> result = instance.getFiboSeries(numberOfElements); assertEquals(expResult, result); numberOfElements = 10; expResult = Arrays.asList(1, 1, 2, 3, 5, 8, 13, 21, 34, 55); result = instance.getFiboSeries(numberOfElements); assertEquals(expResult, result); } }
So we have been able to test for 2 inputs, imagine extending the above for more number of inputs? Unnecessary bloat up in the test code.
JUnit provides a different Runner called Parameterized runner which exposes a static method annotated with @Parameters
.
This method has to be implemented to return the inputs and expected
output collection which will be used to run the test defined in the
class. Lets look at the code which does this:
import java.util.Arrays; import java.util.Collection; import java.util.List; import static org.junit.Assert.assertEquals; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @RunWith(Parameterized.class) public class ParametrizedFiboTest { private final int number; private final List<Integer> values; public ParametrizedFiboTest(FiboInput input) { this.number = input.number; this.values = input.values; } @Parameterized.Parameters public static Collection<Object[]> fiboData() { return Arrays.asList(new Object[][]{ {new FiboInput(1, Arrays.asList(1))}, {new FiboInput(2, Arrays.asList(1, 1))}, {new FiboInput(3, Arrays.asList(1, 1, 2))}, {new FiboInput(4, Arrays.asList(1, 1, 2, 3))}, {new FiboInput(5, Arrays.asList(1, 1, 2, 3, 5))}, {new FiboInput(6, Arrays.asList(1, 1, 2, 3, 5, 8))} }); } @Test public void testGetFiboSeries() { FibonacciUncached instance = new FibonacciUncached(); List<Integer> result = instance.getFiboSeries(this.number); assertEquals(this.values, result); } } class FiboInput { public int number; public List<Integer> values; public FiboInput(int number, List<Integer> values) { this.number = number; this.values = values; } }
This way we would just need to add a new input and expected output in the fiboData()
method to get this working!
Published at DZone with permission of Mohamed Sanaulla, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments