TestNG offers many great features and is definitely more capable as JUnit to build a strong automated Test-Suite. When writing test-cases one important factor is the handling of test-data. With JUnit it is cumbersome to feed different test-data to the same test-code. TestNG solves this much better.
Let’s look at a very simple example. When trying to test an exception with JUnit 4 with different test-data I would need to write something like:
@Test
public void throw_exception_if_wrong_input()
{
try
{
new Foo(“test-data1″);
fail();
}catch(IllegalArgumentException iae){}
try
{
new Foo(“test-data2″);
fail();
}catch(IllegalArgumentException iae){}
try
{
new Foo(“test-data3″);
fail();
}catch(IllegalArgumentException iae){}
}
}
This code has essential problems:
- Because I want to avoid to write two more test-methods (essentialy the same production code is triggered), I am putting three test-cases into one test-method, which is bad practice. This is because test cases aren’t using the tearDown and setUp facilities and cannot guarantee isolation. That is also the reason that I could not use the excpectedException parameter inside the JUnit 4 @Test annotation. Alternative is to really use three test-methods, but code readability then suffers.
- Even though above example is very simplified (only new Foo() is called) the test-code is not expressive. Surely you could improve this by extracting method and giving a good name. But still it is a bit blurry, why we do so and that it is just for using different test-data.
TestNG parameterized test-methods
TestNG does it better and builds the “test-case differs only in test-data” situation into its framework. This is done by building a DataProvider and passing parameters to the test-method. This way code gets more expressive and each different test-data set is executed as an isolated test-case also. Here an example of the TestNG version of above test-cases (I followed the code centric way, you can also configure your DataProvider through an XML file):
@DataProvider(name = “wrong_input”)
public Object[][] createData()
{
//2 dimensions
// x: data-set for one test-case
// y: set of parameters (test-method can contain multiple parameters)
return new Object[][]{
{“test-data-1″},
{“test-data-2″},
{“test-data-3″}
};
}
@Test(expectedExceptions = IllegalArgumentException.class,
dataProvider = “wrong_input”)
public void throw_exception_if_bad_input(String input)
{
new Foo(input)
}
}
0 responses
You must log in to post a comment.