Search code examples
javatestngtestng-dataprovider

How to set dataProvider Name before specifying in my test method


I am trying to check the environment where I will be running my test before setting dataProvider name in my test method.

public class AssignmentSOAPTest {
    private static final String  ctdataProvName=System.getProperty("env");
    

   @BeforeClass
   public void setUp()  {
   }


   @Test(dataProvider = ctdataProvName, dataProviderClass CCCAssignmentSOAPDataProvider.class)
   @Feature("FullCCCAssignment")
   public void tc01FullCCCAssignment(int a,int b,int c) {

    System.out.println("These are the number provided by Data Provider "+  a+"," +b+","+c);

}

}

In this case since my @Test Method is giving me an error: Attribute value must be constant. I discovered this is due because of the way I am setting the constant is not the correct way. I tried different ways to check the environment before setting the constant but could not figure it out. Is there a way to do this?

The reason I would like to check the environment before setting the name is because that way I will need fewer @Test methods in my testScript. I have 4 different environments as well as 10 different test cases. The test cases will be the same among environments but data will be different.

My Data provider class looks like this(did not add all environments and data will be different):

   @DataProvider (name = "ct-environment-data-provider")
   public Object[][] ctDPMethod (Method m){
       switch (m.getName()) {
        case "tc01FullCCCAssignment":
            return new Object[][] {{2, 3 , 5}};
        case "minimumAssignment":
            return new Object[][] {{2, 3, -1}};
        case "updateAssignment":
            return new Object[][] {{1, 3, -1}};
        case "cancelAssignment":
            return new Object[][] {{3, 3, -1}};
        case "saveAssignment":
            return new Object[][] {{8, 3, -1}};
        case "openShopAssignment":
            return new Object[][] {{5, 3, -1}};
        case "casualtyAssignment":
            return new Object[][] {{6, 3, -1}};
   }
   return null;
}

@DataProvider (name = "int-environment-data-provider")
public Object[][] intDPMethod (Method m){
    switch (m.getName()) {
        case "tc01FullCCCAssignment":
            return new Object[][] {{1, 1 , 5}};
        case "minimumAssignment":
            return new Object[][] {{2, 3, -1}};
        case "updateAssignment":
            return new Object[][] {{1, 3, -1}};
        case "cancelAssignment":
            return new Object[][] {{3, 3, -1}};
        case "saveAssignment":
            return new Object[][] {{8, 3, -1}};
        case "openShopAssignment":
            return new Object[][] {{5, 3, -1}};
        case "casualtyAssignment":
            return new Object[][] {{6, 3, -1}};
    }
}

Solution

  • You could use the IAnnotationTransformer class to set the data provider name based on System.getProperty. Annotation transformer can be used to modify the @Test annotation and it would be executed before any test is run.

    public class CustomTransformer implements IAnnotationTransformer {
        private static final String  ctdataProvName = System.getProperty("env");
        
        // include the name of all the test methods in the below list, 
        // for which you need to update the data provider name
        private static final List<String> methods = Arrays.asList("tc01FullCCCAssignment");
    
        @Override
        public void transform(ITestAnnotation annotation,
                              Class testClass,
                              Constructor testConstructor,
                              Method testMethod) {
    
            if(testMethod != null && methods.contains(testMethod.getName())) {
                annotation.setDataProvider(ctdataProvName);
            }
        }
    }
    

    Now, you need to mention the annotation transformer in your suite xml file under the <suite> tag:

    <listeners>
        <listener class-name="com.yourpackage.CustomTransformer" />
    </listeners>
    

    Some listeners could be declared in the test class itself using @Listener annotation, but annotation transformers should be defined ONLY through suite xml. This is because the annotation transformers need to be executed before the test classes are processed so that the annotations are finalized.