Parametric testing show down - No Fluff Just Stuff

Parametric testing show down

Posted by: Andrew Glover on January 9, 2007

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?

Andrew Glover

About Andrew Glover

Andrew is the Engineering Manager for Netflix's Delivery Engineering Team. He and his team are building the next generation Continuous Delivery platform that is facilitating Netflix's rapid global expansion. Before joining Netflix, he served as the CTO of App47, where he lead the development of a SaaS Mobile Application Management platform. Andrew is also the co-author of Addison Wesley's “Continuous Integration” and he actively blogs about software at thediscoblog.com.

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 8
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 4
  • Cloud
  • Automation Tools: Gradle, Git, Jenkins, Sonar
  • HTML5, CSS3, AngularJS, jQuery, Usability
  • Mobile Apps - iPhone and Android
  • More...
Learn More »