2

I'm looking at running Cucumber tests with TestNG. However I am having a issue where all my Scenario are running as one TestNG @Test session. Is there a way to run each Scenario as a separate @Test sessions?

Here is my TestNG xml:

 <suite name="cucumber Suites">
     <test name="cucumber-testing">
         <classes>
            <class name="runners.Run2" />
         </classes>
     </test>
 </suite>

This will call run the following Test class:

import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import cucumber.api.CucumberOptions;
import cucumber.api.testng.AbstractTestNGCucumberTests;
import cucumber.api.testng.CucumberFeatureWrapper;
import cucumber.api.testng.TestNGCucumberRunner;

@CucumberOptions(   features="cucumber/features/example.feature",
                    glue="steps",
                    format={"pretty"}
                )
public class Run2 extends AbstractTestNGCucumberTests{
    private TestNGCucumberRunner tcr;

    @BeforeClass(alwaysRun=true)
    public void beforeClass() throws Exception{
        tcr = new TestNGCucumberRunner(this.getClass());
    }

    @Test(groups="cucumber", description="Runs CucumberFeature", dataProvider="features")
    public void feature(CucumberFeatureWrapper cucumberFeature){
        tcr.runCucumber(cucumberFeature.getCucumberFeature());
    }

    @DataProvider
    public Object[][] features(){
        return tcr.provideFeatures();
    }

    @AfterClass (alwaysRun=true)
    public void afterClass(){
        tcr.finish();
    }
}

I am wondering if there is a way to get the @DataProviderto provide Scenario and the @Test to run Scenario instead of the features?

The reason for this is that I have other TestNG tests with Listeners and that I want to use the same Listeners, reporting for Cucumber tests.

Thanks

T. Daves
  • 40
  • 1
  • 9

3 Answers3

1

What you can try is providing a specific test name for each feature:

@CucumberOptions(   features="cucumber/features/example.feature",
                    glue="steps",
                    format={"pretty"}
                )
public class Run2 extends AbstractTestNGCucumberTests implements ITest {
    private TestNGCucumberRunner tcr;
    private String featureName;

    @BeforeClass(alwaysRun = true)
    public void beforeClass() throws Exception {
        tcr = new TestNGCucumberRunner(this.getClass());
    }

    @BeforeMethod
    public void beforeMethod(Object[] params) {
        CucumberFeatureWrapper cucumberFeature = (CucumberFeatureWrapper) params[0];
        featureName = cucumberFeature.getCucumberFeature().getGherkinFeature().getName();
    }

    @Test(groups = "cucumber", description = "Runs CucumberFeature", dataProvider = "features")
    public void feature(CucumberFeatureWrapper cucumberFeature) {
        tcr.runCucumber(cucumberFeature.getCucumberFeature());
    }

    @Override
    public String getTestName() {
        return featureName;
    }

    @DataProvider
    public Object[][] features() {
        return tcr.provideFeatures();
    }

    @AfterClass(alwaysRun = true)
    public void afterClass() {
        tcr.finish();
    }
}

Let me know if it is the way you'd like.

juherr
  • 5,640
  • 1
  • 21
  • 63
  • Tried this way as well and does not work as I would like it. The only way round my issue is to call the `@BeforeClass` and `@BeforeMethod` in the Cucumber `@Before`. The same with `@After`.Thanks for the help tho. – T. Daves Feb 02 '17 at 17:23
  • @juherr - In this approach if you are creating a web driver instance in the -@BeforeClass or -@Before Method, How will you send it to the test scenario/page objects? – Mike Jun 17 '19 at 15:15
  • 1
    @Mike I'm not sure to understand the relation between the current question and webdriver/page objects. I think you should open a new question. – juherr Jun 19 '19 at 06:25
0

Did you already try:

@CucumberOptions(   features="cucumber/features/example.feature",
                    glue="steps",
                    format={"pretty"}
                )
public class Run2 extends AbstractTestNGCucumberTests{
    private TestNGCucumberRunner tcr;

    @BeforeClass(alwaysRun=true)
    public void beforeClass() throws Exception{
        tcr = new TestNGCucumberRunner(this.getClass());
    }

    @Test(groups="cucumber", description="Runs CucumberFeature")
    public void scenario(){
        for (CucumberFeatureWrapper cucumberFeature : tcr.provideFeatures()) {
            tcr.runCucumber(cucumberFeature.getCucumberFeature());
        }
    }

    @AfterClass (alwaysRun=true)
    public void afterClass(){
        tcr.finish();
    }
}
juherr
  • 5,640
  • 1
  • 21
  • 63
  • The code you have provided still runs all features and scenarios as one `@Test`. I am looking for somthing like `public void scenario(Scenario toRun){ trc.runScenario(toRun); }`. So that the `@DataProvider` will call several `@Test` methods with each having a different scenario – T. Daves Feb 01 '17 at 15:45
  • It won't be possible in your way: Even if you can provide different things for different methods with a data provider, according to Cucumber code (https://github.com/cucumber/cucumber-jvm/blob/master/testng/src/main/java/cucumber/api/testng/TestNGCucumberRunner.java), it looks `trc.runScenario(...)` doesn't exist and Cucumber doesn't allow to run (or get) scenario. – juherr Feb 01 '17 at 20:39
0

The answer is "Yes", you can run each scenario in cucumber as a test using TestNG.

How? It's explained below:

  1. First of all update your Cucumber Maven dependencies from info.cukes to io.cucumber dependencies

  2. Then instead of using method "provideFeatures()" of "TestNGCucumberRunner" in 'your' following code:

    @DataProvider
    public Object[][] features(){
        return tcr.provideFeatures();
    }
    

Use "provideScenarios()" method in @DataProvider.

The following Java code in Cucumber Runner Class worked perfectly for me to run each scenario as TestNG test in feature files:

public class TestRunner {
    private TestNGCucumberRunner testNGCucumberRunner;

    @BeforeClass(alwaysRun = true)
    public void setUpClass() throws Exception {
        testNGCucumberRunner = new TestNGCucumberRunner(this.getClass());
    }

    @Test(groups = "cucumber scenarios", description = "Runs Cucumber 
    Scenarios", dataProvider = "scenarios")
    public void scenario(PickleEventWrapper pickleEvent, CucumberFeatureWrapper 
    cucumberFeature) throws Throwable{
        testNGCucumberRunner.runScenario(pickleEvent.getPickleEvent());
    }
    @DataProvider
    public Object[][] scenarios() {
        return testNGCucumberRunner.provideScenarios();
    }

    @AfterClass(alwaysRun = true)
    public void tearDownClass() throws Exception {
        testNGCucumberRunner.finish();
    }
}

I would be happy to see your problem resolved.

Reference: https://github.com/cucumber/cucumber-jvm/blob/master/testng/README.md

I followed this approach: https://github.com/cucumber/cucumber-jvm/blob/master/examples/java-calculator-testng/src/test/java/cucumber/examples/java/calculator/RunCukesByCompositionTest.java

Pang
  • 9,564
  • 146
  • 81
  • 122
Khan Here
  • 18
  • 3