Parametric testing show down

One of my favorite features of TestNG is its hip parametric testing ability, which allows you to create generic test cases and then vary the test values– you can use parameters from XML files or even use the DataProvider feature for a more rich parameter type. In fact, for awhile, because it’s my bag baby, I’ve been espousing TestNG’s out of the box parametric testing features as a reason to use TestNG as a opposed to JUnit for higher level testing. JUnit 4 , however, now supports parametric tests– and you’ll find that its parametric testing is rather similar to TestNG’s DataProvider.

For example, in TestNG, if I’d like to create a generic test and vary its parameters, I have to do three things:

  1. Create a generic test whose parameters are the parameterized values
  2. Create a DataProvider method, which feeds the values for the test
  3. Link the DataProvider method to the test via the @Test annotation

Hence, I can create a copasetic generic test method as follows:

public void verifyHierarchies(Class clzz, String[] names)
 throws Exception{
  Hierarchy hier = HierarchyBuilder.buildHierarchy(clzz);
  assertEquals(hier.getHierarchyClassNames(), names, "values were not equal");
}

Then I can create a feeder method as follows:

@DataProvider(name = "class-hierarchies")
public Object[][] dataValues(){
 return new Object[][]{
   {Vector.class, new String[] {"java.util.AbstractList",
      "java.util.AbstractCollection"}},
   {String.class, new String[] {}}
  };
}

Note how I have to declare a name for DataProvider, in my case, I dub it class-hierarchies. I can now link the two methods by using the @Test annotation and setting the dataProvider value to the name of my feeder method:

@Test(dataProvider = "class-hierarchies")

That was fairly disco, no? JUnit 4 takes a somewhat similar approach that requires a bit more legwork though:

  1. Create a generic test that takes no parameters
  2. Create a static feeder method that returns a Collection type and decorate it with the @Parameter annotation
  3. Create class members for the parameter types required in the generic method defined in step 1
  4. Create a constructor that takes these parameter types and correspondingly links them to the class members defined in step 3
  5. Specify the test case be run with the Parameterized class via the @RunWith annotation

If I take the same code above and rework it to use JUnit 4 parameterizations, I first must create the generic test:

@Test
public void verifyHierarchies() throws Exception {
 Hierarchy hier = HierarchyBuilder.buildHierarchy(clzz);
 assertEquals("values were not equal",hier.getHierarchyClassNames(), names);
}

Second, I need to create a dynomite feeder method, which functions much like TestNG in that it requires an Object array with matching parameter types.

@Parameters
public static Collection hiearchyValues() {
 return Arrays.asList(new Object[][] {
  {Vector.class, new String[] { "java.util.AbstractList",
     "java.util.AbstractCollection" } },
  {String.class, new String[] {} } });
}

Note how this method is decorated with the @Parameter annotation, man. Next, because the parameters are of types Class and String[], I create two class members:

private Class clzz;
private String[] names;

Step 4 requires I create a constructor, which links values:

public HierarchyBuilderParameterTest(Class clzz, String[] names) {
 this.clzz = clzz;
 this.names = names;
}

Lastly, make sure you specify at the class level that this test be run with the Parameterized class like so:

@RunWith(Parameterized.class)

As you can see, JUnit makes you jump through a few more hoops, yet the fundamental requirements are quite similar to TestNG’s DataProvider feature. When push comes to shove, I still find TestNG’s semantics much simpler, but it’s nevertheless a disco feature to find in JUnit 4. Dig it?

Post to Twitter

Related odds and ends
 

4 Responses to “Parametric testing show down”


  1. [...] Andrew Glover on Parametric testing Go… [...]


  2. [...] The lore of JUnit 4 I’ve written a few articles that cover one of my favorite frameworks; however, that doesn’t mean I don’t dig JUnit 4. In fact, I’ve just published a tutorial on all things JUnit 4. In this tutorial, I show you how to leverage the new and copasetic features enabled by annotations, including parametric tests, exception tests, and timed tests. I also introduce JUnit 4’s flexible fixtures and I show you how to use annotations, rather than suites, to logically group tripped out tests before running them. [...]


  3. [...] Cosmopolitan fixtures in TestNG As I’ve written about before, TestNG supports parametric testing quite copaseticly; in fact, not only can you obtain parameters for tests, but TestNG also supports parametric fixtures. This means you can effectively create generic fixture objects that tailor themselves to particular environments. [...]


  4. [...] One of the most handy features of JUnit 4 is its ability to run parameterized tests, which essentially means you can create a generic test and run it multiple times with various test parameters. In previous versions of JUnit, if you wanted to simulate this same behavior, you’d have to either: [...]