Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

supporting parameters at method level? #823

Closed
JayVem opened this issue Oct 12, 2015 · 12 comments
Closed

supporting parameters at method level? #823

JayVem opened this issue Oct 12, 2015 · 12 comments

Comments

@JayVem
Copy link

JayVem commented Oct 12, 2015

Is it possible to support special parameters at method level?
For instance,

<test name="Regression1">
<groups>
    <run>
      <exclude name="brokenTests"  />
      <include name="checkinTests"  />
    </run>
  </groups>

  <classes>
    <class name="test.IndividualMethodsTest">
      <methods>
        <include name="testMethod" param1="121" param2="1212"  />
      </methods>
    </class>
  </classes>
</test>

I am trying to achieve this by modifying testng code - I would appreciate any guidance/start for this.

@cbeust
Copy link
Collaborator

cbeust commented Oct 12, 2015

No, you should use a @DataProvider for this.

@JayVem
Copy link
Author

JayVem commented Oct 13, 2015

@cbeust, the challenge with @DataProvider is that it cannot be defined from testng.xml? The reason for passing this parameter, is that the data for method comes from a database and this parameter is the primary key. I want to use this key, fetch data, create a dataobject for the method at runtime using reflection. So, in short, even if I use a DataProvider, I have to pass a value at runtime to it, to indicate which set of rows it should pick from database. Please note, this is for a scenario with programmatic usage of testng.

@cbeust
Copy link
Collaborator

cbeust commented Oct 13, 2015

You can define a limited amount of parameters in your testng.xml:

http://testng.org/doc/documentation-main.html#parameters-testng-xml

Cédric

On Mon, Oct 12, 2015 at 9:03 PM, JayVem notifications@github.com wrote:

@cbeust https://github.com/cbeust, the challenge with @dataProvider is
that it cannot be defined from testng.xml? The reason for passing this
parameter, is that the data for method comes from a database and this
parameter is the primary key. I want to use this key, fetch data, create a
dataobject for the method at runtime using reflection. So, in short, even
if I use a DataProvider, I have to pass a value at runtime to it, to
indicate which set of rows it should pick from database. Please note, this
is for a scenario with programmatic usage of testng.


Reply to this email directly or view it on GitHub
#823 (comment).

@JayVem
Copy link
Author

JayVem commented Oct 13, 2015

@cbeust Aren't these parameters at suite level? What if I wanted to create a complex data type at method level. For instance, consider this code...

public class EmployeeBenefitsCalculator {

    @Test
    public void calculateBenefits(Employee employee) {
        //do something with employee here.
    }
}

The Employee parameter that is being sent to calculateBenefits method has to be created from the database. How would I achieve this? I would like to pass a primary key and inside the calculateBenefits method, I want to read this primary key, fetch data from db and create an employee object for that test run. I know it sounds complicated. I think this is what I am looking for -

public class EmployeeBenefitsCalculator {

    @Test
    public void calculateBenefits(Employee employee) {
        employee = DataStore.fetch("id_from_testng_xml");
    }
}

How do I provide parameters to a dataprovider for a test at run time? How easy a change is it to create this behavior by altering testng source?

@juherr
Copy link
Member

juherr commented Oct 13, 2015

You can mix data provider + parameters. Your data provider will take primary key from the parameter and will create your Employee object + pass any other attributes. Then your test method will use the data provider and its attributes.
Easy! ;)

@JayVem
Copy link
Author

JayVem commented Oct 14, 2015

@juherr Could you give me an example of how I can I have multiple parameters at method level, each going to a dataprovider ?

@JayVem
Copy link
Author

JayVem commented Oct 14, 2015

@juherr To simplify my question, I am programmatically generating a testng.xml. Now, let's say I have a method modifyEmployee(Employee employee). I need to create an xml in such a way that this method is invoked 4 times, but each time with a different Employee. I would know the primary key of each of these employees at the time of creating testng.xml. So, what is the best way to achieve what I am trying to do?

@juherr
Copy link
Member

juherr commented Oct 14, 2015

I suppposed @dataProvider can work with @parameters but I'm not sure (I should test it one day).
BTW, if I understand what you want, you can just try parameters on test level (parameters on method level don't exist):

<suite>
<test name="Regression1">
<parameter name="param1" value="121" />
<parameter name="param2" value="1212" />
<groups>
    <run>
      <exclude name="brokenTests"  />
      <include name="checkinTests"  />
    </run>
  </groups>

  <classes>
    <class name="test.IndividualMethodsTest">
      <methods>
        <include name="testMethod"  />
      </methods>
    </class>
  </classes>
</test>

<test name="Regression2">
<parameter name="param1" value="454" />
<parameter name="param2" value="4545" />
<groups>
    <run>
      <exclude name="brokenTests"  />
      <include name="checkinTests"  />
    </run>
  </groups>

  <classes>
    <class name="test.IndividualMethodsTest">
      <methods>
        <include name="testMethod"  />
      </methods>
    </class>
  </classes>
</test>
<suite>

You should ask your question on Staskoverflow or the mailing list if you want more ideas ;)

@drapostolos
Copy link
Contributor

Actually, parameters on method level exists. Here is an example:

<suite name="my-suite" verbose="1">
    <test name="my-test">
        <classes>
            <class name="testng.ex1.TestParams">
                <methods>
                    <include name="m1">
                        <parameter name="key1"  value="val1"/>
                        <parameter name="key2"  value="val2"/>
                    </include>
                    <include name="m2">
                        <parameter name="key1"  value="valA"/>
                        <parameter name="key2"  value="valB"/>
                    </include>
                </methods>
            </class>
        </classes>
    </test>
</suite>
package testng.ex1;

import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class TestParams {

    @Test
    @Parameters({ "key1", "key2" })
    public void m1(String key1, String key2) throws Exception {
        System.out.println(key1 + ", " + key2);
    }

    @Test
    @Parameters({ "key1", "key2" })
    public void m2(String key1, String key2) throws Exception {
        System.out.println(key1 + ", " + key2);
    }
}

@juherr
Copy link
Member

juherr commented Oct 14, 2015

👍 Good to know! I've never seen it before.

@JayVem I close the issue as it already exists.

@juherr juherr closed this as completed Oct 14, 2015
@drapostolos
Copy link
Contributor

another approach is to use a data-provider that fetches the keys from testng.xml. See example:

<suite name="my-suite" verbose="1">
    <test name="my-test">
        <classes>
            <parameter name="keys" value="key1,key2,key3,key4" />
            <class name="testng.ex2.TestParams" />
        </classes>
    </test>
</suite>
package testng.ex2;

import java.util.Arrays;
import java.util.List;

import org.testng.ITestContext;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class TestParams {

    @Test(dataProvider = "dp")
    public void m1(Employee e) throws Exception {
        System.out.println("name: " + e.getName() + ", age: " + e.getAge());
    }

    @DataProvider(name = "dp")
    @Parameters("keys")
    public Object[][] createData(ITestContext ctx) {
        String keysString = ctx.getCurrentXmlTest().getLocalParameters().get("keys");
        List<String> keys = Arrays.asList(keysString.split(","));

        Object[][] result = new Object[keys.size()][1];
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            result[i] = new Object[] { new Employee(key) };
        }
        return result;
    }
}
package testng.ex2;

public class Employee {

    private final String name;
    private final int age;

    public Employee(String key) {
        // use 'key' to lookup employee in database
        name = key + "_name"; // dummy value
        age = 41; // dummy value
    }

    String getName() {
        return name;
    }

    int getAge() {
        return age;
    }
}

@JayVem
Copy link
Author

JayVem commented Oct 14, 2015

Thanks @drapostolos , I think dataprovider with testcontext sounds like it will do. I will try this out. Thank you so much for the quick answer!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants