3

I'm using the TestNG DataProvider to read a datapool.xls file that contains 1017 test cases and 214 columns in a class called ReadData.

I then pass the 214 String parameters into an @Test annotation in a separate class called EnterData.

@Test(dataProvider="autodata", dataProviderClass = ReadAutoData.class)
public void autoentry(String Quote, String Garage_Zip, etc...) {

I have created a for loop within @Test to only perform the actions for ceratin iterations (say 1-10), which does work by only entering 10 test cases in total. My problem is that at the end of the run it still shows "Total tests run: 1017" instead of only the 10 that actually did anything because of the for loop.

// Start for loop for entering auto policies
for (int a = start; a <= end; a++)
{
    if (quote == a)
    {       
        System.out.println("Tier = " + Tier);                       
    } 
}

I realize why it shows the total number of tests run as being the entire datapool because it technically passed in and ran through everything in the datapool, I just can't figure out how to only have it show the number of tests that actually ran.

Basically, I'm looking for a way to put the @Test annotation itself in the for loop, possibly?...

Edit:

Here is my current code for reading the datapool in the ReadAutoData Class:

@DataProvider(name = "autodata")
public static Object[][] autodata() {
Object[][] arrayObject = getExcelData("C:/dev/AutoDP.xls","NON-COMBO-DP");
return arrayObject;
}

/**
 * @param File Name
 * @param Sheet Name
 * @return
 */
public static String[][] getExcelData(String fileName, String sheetName) {
    String[][] arrayExcelData = null;
    try {
        FileInputStream fs = new FileInputStream(fileName);
        Workbook wb = Workbook.getWorkbook(fs);
        Sheet sh = wb.getSheet(sheetName);

        int totalNoOfCols = sh.getColumns();
        int totalNoOfRows = sh.getRows();

        arrayExcelData = new String[totalNoOfRows-1][totalNoOfCols];

        for (int i= 1 ; i < totalNoOfRows; i++) {

            for (int j=0; j < totalNoOfCols; j++) {
                arrayExcelData[i-1][j] = sh.getCell(j, i).getContents();
            }

        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
        e.printStackTrace();
    } catch (BiffException e) {
        e.printStackTrace();
    }
    return arrayExcelData;
}

Edit 2:

Here's where I'm at so far out of the 1017 test cases, I have gotten it to now show 1007 Skips by adding the following at the beginning of my for loop:

// Start for loop for entering auto policies
    for (int a = start; a <= end; a++)
    {
        if (quote < start) throw new SkipException("Testing skip.");
        if (quote > end) throw new SkipException("Testing skip.");

        if (quote == a)
        {

            System.out.println("Starting Iteration = " + Quote);

however, it is still showing 1017 Tests run.

Dustin N.
  • 785
  • 1
  • 14
  • 32
  • are you okay with showing 10 executed rest skipped ? – Shamik Jul 09 '15 at 11:03
  • Yes, that is exactly what I am wanting. – Dustin N. Jul 09 '15 at 17:39
  • what is stopping you from placing the decision logic for your testiterations into your dataprovider itself, thereby sending only the 10 tests which you want to run? – Mrunal Gosar Jul 09 '15 at 18:46
  • Because I'm not exactly sure how to only tell the @DataProvider which rows to grab. I'm currently trying to implement Crazy's method. – Dustin N. Jul 09 '15 at 19:25
  • You can have the implementation of sending the Indexes to DataProvider from Test itself. You can check this article https://www.pawangaria.com/post/testng/limit-certain-test-iterations-in-testng-dataprovider/ – user1344022 Sep 29 '20 at 13:24

3 Answers3

4

The only way you can achieve that is to understand how the TestNG framework executes.

Which means:

  1. SkipException is not the solution as it will always count all the test cases, even if they are skipped.
  2. The number of tests is the number of rows returned by the @DataProvider method.

The solution is then to return the correct number of test cases from the method annotated by @DataProvider:

public class ReadAutoData {
    private static int indexFrom;
    private static int indexTo;

    @DataProvider(name = "autodata")
    public static Object[][] autodata() {
        // you should probably cache this into static variable
        Object[][] arrayObject = getExcelData("C:/dev/AutoDP.xls","NON-COMBO-DP"); 

        return java.util.Arrays.copyOfRange(arrayObject, indexFrom, indexTo);
    }

    public Class<?> autoDataWithinRange(int from, int to) {
        indexFrom = from;
        indexTo   = to;

        return ReadAutoData.class;
    }
}

@Test(dataProvider="autodata", dataProviderClass = ReadAutoData.autoDataWithinRange(0, 10))
public void autoentry(String Quote, String Garage_Zip, etc...) {

This would work if you are not running test concurrently. If you are, you can still use it with small modification using ThreadLocals.

Crazyjavahacking
  • 9,343
  • 2
  • 31
  • 40
  • Well, I've tried implementing this and when trying to pass the dataProviderClass to @Test as you described, I'm getting the following error: "The value for annotation attribute Test.dataProviderClass must be a class literal". – Dustin N. Jul 09 '15 at 19:35
  • You are right. In that case you will have to do it a little bit differently, but the point remains the same. – Crazyjavahacking Jul 09 '15 at 19:45
  • Got it!!!! Thank you so much for your help. I have learned quite a bit through this. I now have the @DataProvider reading a .properties file to get the iterations to run from the datapool and pass that into the indexFrom (-1) and indexTo and it's working like a dream. – Dustin N. Jul 09 '15 at 20:23
1

You can always throw TestNG's SkipException to mark skipped executions as skipped rather than passed. SkipException is a special exception that is not recognized as a failure.

Other that this, you can modify ReadAutoData.autodata to return fewer data sets (rows), e.g. only first 10 from your thousands you have in the file.

Piotr Findeisen
  • 19,480
  • 2
  • 52
  • 82
  • I like where you are going, but I guess I cannot figure out how to implement it correctly. When I use the SkipException, it runs through the 10 test cases, however, shows all 1017 skipped. I'm not sure how to get it to load only the test cases I want ran. Say I want to start at 20 and go to 30, etc... – Dustin N. Jul 09 '15 at 17:43
  • See Edit 2. I have gotten it to at least show how many tests were skipped now. The problem is it is still showing all 1017 tests as being ran. – Dustin N. Jul 09 '15 at 18:27
0

How about creating listener class by implementingIInvokedMethodListener and implementing method beforeInvocation(IInvokedMethod method, ITestResult tr) In side that you can take the test result object and get the params and decide what to do for that data set.

Object [] params = tr.getParameters();
// put some logic on params and decide
if ( params is something ) {
tr.setStatus(ITestResult.SKIP);
}

I am assuming that you want to run or not run based on the params.

Shamik
  • 1,591
  • 2
  • 16
  • 36