Ankit Singh
Ankit Singh

Reputation: 77

how to pass dataprovider to any test in testNG when dataset has data not specific to this testcase

I am trying to build a Selenium hybrid framework using TestNG wherein i am getting data from my excel datasheet. I am trying to use DataProvider of testNG, But problem is since my datasheet contains data which belongs to different test case (for eg. 2 rows for add user, 1 rows for modify user, some rows for searching user etc)

since my dataprovider will return all the data from datasheet and passing it to any particular testCase that will run for all row of dataprovider will cause problem (eg. create user will need 5 parameter but the data of edit user will not be sufficient to it).

how can we handle this problem?

Upvotes: 0

Views: 1310

Answers (1)

Krishnan Mahadevan
Krishnan Mahadevan

Reputation: 14746

Here's how you do this:

  • Within your .xls file, create a sheet which represents a particular functionality. (For e.g, login, compose, address-book etc., if I were to be taking the example of an emailing application)
  • Now each sheet would have test data for various test cases, that test out that particular functionality.
  • In your @Test method, you can create a new custom annotation (this would be a marker annotation), which would indicate the "sheet" name from which the data provider should be retrieving data from. If you are not keen on creating a new custom annotation, then you can make use of the "description" attribute of the @Test annotation to capture this information.
  • TestNG can natively inject a Method object to your @DataProvider annotated method. Here the Method object that was injected would represent the @Test method for which the data provider is about to be invoked. So now you can retrieve the sheet name, either from the new custom annotation (or) from the description attribute of the @Test annotation to figure out which sheet name to query for data.

That should solve your issue.

Here's a sample that demonstrates the overall idea. You would need to enrich the data provider, such that it uses the sheet name to query data from the excel spreadsheet. My sample just excludes all of that, for the sake of demonstration.

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.METHOD;

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({METHOD})
public @interface SheetName {
    String value() default "";
}
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.lang.reflect.Method;

public class TestClass {

  @Test(dataProvider = "dp")
  @SheetName("one")
  public void test1(String name) {
    System.err.println("Name is " + name);
  }

  @Test(dataProvider = "dp")
  @SheetName("two")
  public void test2(int age) {
    System.err.println("Age is " + age);
  }

  @DataProvider(name = "dp")
  public Object[][] getData(Method method) {
    String sheetName = getSheetName(method);
    if (sheetName == null) {
      // Handle the case, wherein our custom annotation is missing. That means the test perhaps
      // expects
      // either all of the data, or it could be a error case.
      return new Object[][] {{}};
    }
    if ("one".equalsIgnoreCase(sheetName)) {
      return new Object[][] {{"Cedric"}, {"Beust"}};
    }
    if ("two".equalsIgnoreCase(sheetName)) {
      return new Object[][] {{1}, {2}};
    }
    // Handle the case, wherein we had a valid sheet name, but it represents a sheet that cant be
    // found in our
    // excel spreadsheet.
    return new Object[][] {{}};
  }

  private String getSheetName(Method method) {
    SheetName sheetName = method.getAnnotation(SheetName.class);
    if (sheetName == null || sheetName.value().trim().isEmpty()) {
      return null;
    }
    return sheetName.value();
  }
}

Upvotes: 1

Related Questions