Testng: Add an API for custom test method parameter injection

Created on 3 Mar 2015  ·  12Comments  ·  Source: cbeust/testng

I need a way to inject a custom parameter into TestNG's test methods. The parameter is my own object constructed dynamically at runtime from test method annotations. The custom parameter is not known to TestNG, it's my own type, e.g.:

@com.mypackage.MyAnnotation("someValue)"
@org.testng.Test
public void test(MyCustomObject val) {
    ...
}

It looks like right now I cannot do it easily.

Can we add such functionality/SPI? What is the current easiest way to achieve that?

injection Feature request

Most helpful comment

Would be very useful I have the same needs

All 12 comments

I don't want to use @DataProvider annotation.

Why don't you want to use @DataProvider, it's the easiest approach by far
(just a few lines of code).

Cédric

On Tue, Mar 3, 2015 at 6:09 AM, Crazyjavahacking [email protected]
wrote:

_I don't want to use @DataProvider annotation._

Reply to this email directly or view it on GitHub
https://github.com/cbeust/testng/issues/612#issuecomment-76951265.

The problem is that the object I want to inject is dynamically created based on the data inside annotations on test method.

In my initial example, I need to parse the content of @MyAnnotation and based on that I need to create an instance of MyCustomObject.

What is stopping you from doing all that in the data provider?

Cédric

On Tue, Mar 3, 2015 at 3:12 PM, Crazyjavahacking [email protected]
wrote:

The problem is that the object I want to inject is dynamically created
based on the data inside annotations on test method.

In my initial example, I need to parse the content of @MyAnnotation and
based on that I need to create an instance of MyCustomObject.

Reply to this email directly or view it on GitHub
https://github.com/cbeust/testng/issues/612#issuecomment-77060429.

The functionality is not really parameterized testing and I also don't want to use data providers, e.g.:

@Columns("col1 | col2 || val)"
@Rows  ({"a    | b    || c",
         "d    | e    || f})
@org.testng.Test
public void test1(MyCustomObject val) {
    // MyCustomerObject is created from the annotation values
    // some menipulation with val ...
}

@Columns("col1 | col2 || val)"
@Rows  ({"1    | 2    || a",
         "3    | 3    || b})
@org.testng.Test
public void test1(MyCustomObject val) {
    // MyCustomerObject is created from the annotation values
    // some menipulation with val ...
}

so I don't think data providers are a good approach here

Would be very useful I have the same needs

The idea is interesting but as @cbeust said a long time ago, a data provider is a good workaround.
According to the previous sample:

@Columns("col1 | col2 || val)")
@Rows(  {"a    | b    || c",
         "d    | e    || f"})
@Test(dataProvider = "dp")
public void test1(MyCustomObject val) {
    // MyCustomerObject is created from the annotation values
    // some menipulation with val ...
}

@Columns("col1 | col2 || val)"
@Rows(  {"1    | 2    || a",
         "3    | 3    || b"})
@Test(dataProvider = "dp")
public void test1(MyCustomObject val) {
    // MyCustomerObject is created from the annotation values
    // some menipulation with val ...
}

@DataProvider
public static MyCustomObject[] dp(Method m) {
    Columns colums = m.getAnnotation(Columns.class);
    Rows rows = m.getAnnotation(Rows.class);
    MyCustomObject[] results = new MyCustomObject[rows.values().length];
    for (int i=0; i < rows.values().length; i++) {
        String value = rows.values()[i];
        // extract params with custom business
        results[i] = new MyCustomObject(/* params */);
    }
    return results;
}

this is true @juherr, i ended doing it this way. But, the only thing that misses is the abilitty to set a default dataProvider for all tests, in my case, my data provider is generics and passes only if there is certain annotations

i think that a combination of the dataProvider and adding the ability to set a default provider or provider class would do the trick and will open a hole new possibilities

@g13013 You mean something like

public class UseMyDataProvider implements IAnnotationTransformer {
  public void transform(ITest annotation, Class testClass, Constructor testConstructor, Method testMethod) {
    if (/* business logic (for example: testMethod has expected annotations) */) {
      annotation.setDataProviderClass(MyExternalClassWithDataProvider.class);
      annotation.setDataProvider("dataprovider name");
    }
  }
}

I would also love to be able to use Guice to inject parameters in tests.
DataProvider + IAnnotationTransformer is an interesting workaround but it lack flexibility (for example it is impossible to set the IAnnotationTransformer via @Listeners)

it is impossible to set the IAnnotationTransformer via @Listeners

@gjuillot It could be a feature request. Could you open an issue with that?

I'll do. But still, the best ever for me would be to have the possibility to use Guice to inject parameters in tests.

Was this page helpful?
0 / 5 - 0 ratings