1

Given my data CSV file:

jones;1293039,
smith;2938949,
johnson;1203939,
clark;8293044

And my DataProvider:

@DataProvider(name="data")
public Iterator<Object[]> custDataProvider(){
    try{
        Scanner scanner = new Scanner(new File(CSV_FILE)).useDelimiter(DELIMITER);
        return new Iterator<Object[]>() {
            @Override
            public boolean hasNext() {
                return scanner.hasNext();
            }

            @Override
            public Object[] next() {
                return new Object[]{scanner.next().split(";")[0]};
            }
        };
    }catch(FileNotFoundException e){
        e.printStackTrace();
        return null;
    }
}

I can iterate over the data values based on the index of the array, splitting on the ; So, the below method will print the name attribute at index 0:

@Test(dataProvider = "data")
public void createNewCustomer(String name) {
    System.out.println(name);
}

And if I change the array index to [1] it will print the customer number. But I wonder if I can parameterize the DataProvider method with an int index like so:-

@DataProvider(name="data")
public Iterator<Object[]> custDataProvider(int index){
    try{
        Scanner scanner = new Scanner(new File(CSV_FILE)).useDelimiter(DELIMITER);
        return new Iterator<Object[]>() {
            @Override
            public boolean hasNext() {
                return scanner.hasNext();
            }

            @Override
            public Object[] next() {
                return new Object[]{scanner.next().split(";")[index]};
            }
        };
    }catch(FileNotFoundException e){
         e.printStackTrace();
         return null;
    }
}

And call based on whether I want the customer name or number like so:-

@Test(dataProvider = "data")
public void createNewCustomer(String name) {
    String customerName = custDataProvider(0);
    System.out.println(name);
}

@Test(dataProvider = "data")
public void createNewCustomer(String number) {
    String customerNumber = custDataProvider(1);
    System.out.println(number);
}

The behavior I'm seeing is that it skips the tests entirely.

2
  • Assume that you can. How are you going to pass index number to your data provider? From where? – Alexey R. Aug 19 '20 at 10:52
  • What about you read the file, create a data structure, and walk through this structure, passing each element to a function that performs the check you want? @DataProvider requires basically the same support code and adds a bunch of limitations; totally bloated. – João Farias Aug 19 '20 at 11:25
1

You can't specify a number like you do, but you can use reflection and customize @DataProvider behavior depending on the method it runs. As per TestNG documentation:

If you declare your @DataProvider as taking a java.lang.reflect.Method as first parameter, TestNG will pass the current test method for this first parameter. This is particularly useful when several test methods use the same @DataProvider and you want it to return different values depending on which test method it is supplying data for.

1

Don't change input argument of custDataProvider method. Use custDataProvider without any input arguments. Just change the input arguments of createNewCustomer from String to Iterator. Exactly like whatever you return from custDataProvider.

Then you can iterate through it in createNewCustomer.

       @DataProvider(name="data")
    public Iterator<Object[]> custDataProvider(){
        try{
            Scanner scanner = new Scanner(new File(CSV_FILE)).useDelimiter(DELIMITER);
            return new Iterator<Object[]>() {
                @Override
                public boolean hasNext() {
                    return scanner.hasNext();
                }
    
                @Override
                public Object[] next() {
                    return new Object[]{scanner.next().split(";")[0]};
                }
            };
        }catch(FileNotFoundException e){
            e.printStackTrace();
            return null;
        }
    }


    @Test(dataProvider = "data")
    public void createNewCustomer(Iterator<Object[]> names) {
        while(names.hasNext()){
            //Do what ever you want
        }

    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.