In this post we will learn about TestNG @DataProvider
annotation to parameterize your tests in order to write data-driven tests. In data-driven testing, we run the same tests multiple times but with different sets of data which we pass into test methods using parameters.Let’s get going.
Let’s take a simple Calculator example:
package com.websystique.testng; public class Calculator { public int add(int a, int b){ return a+b; } }
Above class have only one method. In traditional @Test, in order to test add method, we would be hard-coding a certain value for a, b and expected outcome right into @Test.
But what if we want to test this add method against several different values for a, b and expected outcome. Code duplication of test method is not a good option. In these kind of situations, we can use @DataProvider annotation.
Below is a trivial test class to test add method:
package com.websystique.testng; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class TestNGDataProviderExample { @DataProvider(name = "addMethodDataProvider") public Object[][] dataProvider() { return new Object[][] { { 2, 5, 7 }, { 3, 7, 10 }, { 4, 5, 9 } }; } @Test(dataProvider = "addMethodDataProvider") public void testAddMethod(int a, int b, int result) { Calculator calculator = new Calculator(); Assert.assertEquals(calculator.add(a, b), result); } }
A method annotated with @DataProvider acts as data-provider for other tests. The annotated method must return an Object[][] where each Object[] can be assigned the parameter list of the test method. The @Test method that wants to receive data from this DataProvider needs to use a dataProvider
name equals to the name of this annotation.
In above example, we have created a data-provider method using @DataProvider annotation and assigned a name to it. This data-provider method, returns different sets of parameters (a,b,sum). Then in our test testAddMethod, we refer to the same data-provider using it’s name. With this way, the @Test method testAddMethod will be called 3 times, as there are 3 sets of parameter in Object[][] of data-provider method. Each item in object[][], maps uniquely to parameters a,b & expected outcome in testAddMethod.
Run above test. Following is the output.
PASSED: testAddMethod(2, 5, 7) PASSED: testAddMethod(3, 7, 10) PASSED: testAddMethod(4, 5, 9) =============================================== Default test Tests run: 3, Failures: 0, Skips: 0 ===============================================
You can see that @Test testAddMethod was executed 3 times as there were 3 sets of parameter provided by @DataProvider.
Multiple DataProviders Example
Let’s suppose we have multiple methods to test this time. It means we will need multiple data-providers, one for each test method.
package com.websystique.testng; public class Calculator { public int add(int a, int b){ return a+b; } public int subtract(int a, int b){ return a-b; } public int multiply(int a, int b){ return a * b; } }
Let’s also refactor the @DataProvider in a separate class to make it more manageable.
Below is an independent class with all @DataProvider’s in one place. This way our actual Test class will not be polluted.
package com.websystique.testng; import org.testng.annotations.DataProvider; public class CalculatorDataProvider { @DataProvider(name = "addMethodDataProvider") public static Object[][] addMethodDataProvider() { return new Object[][] { { 2, 5, 7 }, { 3, 7, 10 }, { 4, 5, 9 } }; } @DataProvider(name = "subtractMethodDataProvider") public static Object[][] subtractMethodDataProvider() { return new Object[][] { { 2, 5, -3 }, { 3, 7, -4 }, { 24, 5, 19 } }; } @DataProvider(name = "multiplyMethodDataProvider") public static Object[][] multiplyMethodDataProvider() { return new Object[][] { { 2, 5, 10 }, { 3, 7, 21 }, { 4, 5, 20 } }; } }
Now let’s write the test class to test all 3 methods of Calculator class.
package com.websystique.testng; import org.testng.Assert; import org.testng.annotations.Test; public class TestNGMultipleDataProviderExample { @Test(dataProvider = "addMethodDataProvider", dataProviderClass = CalculatorDataProvider.class) public void testAddMethod(int a, int b, int expectedResult) { Calculator calculator = new Calculator(); Assert.assertEquals(calculator.add(a, b), expectedResult); } @Test(dataProvider = "subtractMethodDataProvider", dataProviderClass = CalculatorDataProvider.class) public void testSubtractMethod(int a, int b, int expectedResult) { Calculator calculator = new Calculator(); Assert.assertEquals(calculator.subtract(a, b), expectedResult); } @Test(dataProvider = "multiplyMethodDataProvider", dataProviderClass = CalculatorDataProvider.class) public void testMultiplyMethod(int a, int b, int expectedResult) { Calculator calculator = new Calculator(); Assert.assertEquals(calculator.multiply(a, b), expectedResult); } }
Notice a new dataProviderClass
attribute within @Test annotation. This attribute allows you to specify the data-provider class which will contain the data-provider this @Test method will be using. Code is cleaner this time, and all methods got there own data-providers.
Execute above Tests. Following is the outcome:
PASSED: testAddMethod(2, 5, 7) PASSED: testAddMethod(3, 7, 10) PASSED: testAddMethod(4, 5, 9) PASSED: testMultiplyMethod(2, 5, 10) PASSED: testMultiplyMethod(3, 7, 21) PASSED: testMultiplyMethod(4, 5, 20) PASSED: testSubtractMethod(2, 5, -3) PASSED: testSubtractMethod(3, 7, -4) PASSED: testSubtractMethod(24, 5, 19) =============================================== Default test Tests run: 9, Failures: 0, Skips: 0 ===============================================
It’s evident that all three @Test methods took data from there respective dataProviders, independent of others.
That’s it.
References
If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help improve further our learning process.