If your scenario needs to be for different parametric values, instead of creating a new test case for each set of parameters, JUnit allows you to create a generic test case and run the test multiple times, once for every parameter you’ve create. In this article, we see couple of examples of JUnit parametric testing.
Single Parameter Testing
In the below example, we will show how to run some generic tests on collection for each implementation of Collection
, like ArrayList
, >code>HashSet and LinkedList
.
If you notice all the tests are generic in nature and we don’t use any method parameter to pass in the actual implementation.
Each instance of the test class CollectionTestUsingParameters
will be constructed with the default constructor. The test depends on collection object, the actual collection instance will be inject to the field annotated by @Parameter
. There can be more than one parameter. The test data is either as object array or Iterable
of object. If more than one parameter, the data will be a two dimensional Object[][]
array or Iterable<Object[]>
.
The data feeder method arguments()
is a public static method that is annotated with @Parameters
annotation.
@Parameters public static Iterable<Collection<Integer>> arguments() { return Arrays.<Collection<Integer>> asList(new ArrayList<Integer>(), new HashSet<Integer>(), new LinkedList<Integer>()); }
The data is injected using class member field annotated with <[email protected]
Finally, the test case must be run with the Parameterized
class via the @RunWith
annotation.
CollectionTestUsingParameters:
package com.javarticles.junit; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import org.junit.Before; 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 CollectionTestUsingParameters { @Parameter public Collection<Integer> collection; @SuppressWarnings("unchecked") @Parameters public static Iterable<Collection<Integer>> arguments() { return Arrays.<Collection<Integer>> asList(new ArrayList<Integer>(), new HashSet<Integer>(), new LinkedList<Integer>()); } @Before public void populateCollection() { collection.clear(); collection.add(1); collection.add(2); collection.add(3); } @Test public void sizeCheck() { assertEquals(3, collection.size()); } @Test public void getElement() { Iterator<Integer> itr = collection.iterator(); assertEquals(new Integer(1), itr.next()); assertEquals(new Integer(2), itr.next()); assertEquals(new Integer(3), itr.next()); } @Test public void removeElement() { assertTrue(collection.remove(3)); assertEquals(2, collection.size()); assertFalse(collection.contains(3)); } }
When running a parameterized test class, instances are created for the cross-product of the test methods and the test data elements. We have three tests and three set of data, the test has run nine times.
Output:
Multiple Parameters Testing
In the below example, we show a group of parameters. Main purpose is to evaluate a calculation which can be a sum or multiplication. We have one generic test that evaluates the expression using the inputs x
and y
, the calculation is represented by the interface ICalculation
.
Here is the data feeder method. You can either return as Object[][]
or an Iterable
of Object[]
. The data set includes an instance o fICalculation
, x
, y
values and the result expected.
@Parameters public static Iterable<Object[]> arguments() { return Arrays.asList(new Object[][] {{new Sum(), 2, 3, 5}, {new Multiply(), 2, 3, 6}}); }
We have three parameters, each parameter is injected into a class member defined. Index range must start at 0.
CalculatorUsingParameters:
public class CalculatorUsingParameters { @Parameter(0) public ICalculator calculator; @Parameter(1) public Integer x; @Parameter(2) public Integer y; @Parameter(3) public Integer result; ... }
Calculator interface:
ICalculator:
package com.javarticles.junit; public interface ICalculator { Integer evaluate(int x, int y); }
Concrete classes of calculator to be tested:
Sum:
package com.javarticles.junit; public class Sum implements ICalculator { public Integer evaluate(int x, int y) { return x + y; } }
Multiply:
package com.javarticles.junit; public class Multiply implements ICalculator { public Integer evaluate(int x, int y) { return x * y; } }
CalculatorUsingParameters:
package com.javarticles.junit; import static org.junit.Assert.assertEquals; import java.util.Arrays; 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 CalculatorUsingParameters { @Parameter(0) public ICalculator calculator; @Parameter(1) public Integer x; @Parameter(2) public Integer y; @Parameter(3) public Integer result; @Parameters public static Iterable<Object[]> arguments() { return Arrays.asList(new Object[][] {{new Sum(), 2, 3, 5}, {new Multiply(), 2, 3, 6}}); } @Test public void evaluateOperation() { assertEquals(result, calculator.evaluate(x, y)); } }
Download the source code
This was an example about JUnit parametric testing.