In chapter 4, Koskela described about test patterns and one of them is Parameterized Test. To apply this pattern, we need to follow the rule to write the test class as below:
+ The test class must be annotated by
@RunWith(Parameterized.class)
,+ Supply a static method, is annotated by
@Parameters
and returns a Collection<Object[]>
or its subclass,+ And we need to write a constructor which has parameters for expected value and input values.
Example:
@RunWith(Parameterized.class)
public class ParameterizedTest {
// Provide parameterized data
@Parameters
public static Collection<Object[]> parameters() {
Object[][] data = new Object[][] {
{ 0, 0, 0 }, { 1, 1, 0 },
{ 2, 1, 1 }, { 3, 2, 1 },
{ 4, 3, 1 }, { 5, 5, 0 },
{ 6, 8, -2 } };
return Arrays.asList(data);
}
public int expected, input1, input2;
// Data is bound through constructor
public ParameterizedTest(int expected, int input1,
int input2) {
this.expected = expected;
this.input1 = input1;
this.input2 = input2;
}
//Test method invoked once for each data set
@Test
public void executeParameterizedTest() throws Exception {
assertEquals(expected, new Calculator().add(input1,
input2));
}
}
It looks very complicated, huh? Now, I will "convert" it to TestNG.
After awhile, I found that TestNG's
@DataProvider
can do the same thing. And here is the rule to write test class with TestNG following Parameterized Test pattern:+ Supply a method (don't need to be
static
) is annotated by @DataProvider(name = "dataProviderName")
and returns Object[][]
,+ Test method is annotated by
@Test(dataProvider = "dataProviderName")
and has parameters as same as the Object[]
's elements in data is supplied from data providerThe above source code after was "converted":
public class ParameterizedTest {
@DataProvider(name = "data")
public Object[][] parameters() {
return new Object[][] {
{ 0, 0, 0 }, { 1, 1, 0 },
{ 2, 1, 1 }, { 3, 2, 1 },
{ 4, 3, 1 }, { 5, 5, 0 },
{ 6, 8, -2 } };
}
@Test(dataProvider = "data")
public void executeParameterizedTest(int expected,
int input1,
int input2)
throws Exception {
assert (expected == new Calculator().add(input1,
input2));
}
}
The test class is written with TestNG is much simpler also you can have many data providers as you want. And what will happen if you want to test the Calculator for substraction? If you use JUnit 4 as unit testing framework, seems you need to write another test class.
1 comment:
I have also implemented a JUnit plugin to provide better parameterized tests to JUnit (similar to TestNG). As the internal structure of TestNG is a bit different from JUnit, it’s not completely equal but IMHO it provides the most important features for parameterized testing.
See https://github.com/TNG/junit-dataprovider
Feedback welcome :-)
Post a Comment