0
votes

I have implemented Testng and Cucumber for my selenium Project. I am running my Test Cases by running the Testng.xml where I have redirected them to Testng Runner File. The only difference in each Runner file is the @tag which is linked to a Cucumber feature scenario hence I have created separate runner files with @sanity @regression etc. I want to avoid creating so many runner files as only the @tag is a variable. I want to parameterize the annotation so that I just have one runner file.


package com.ibm.wce.scbn.cc.runner;

import org.apache.log4j.Logger;
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.CucumberFeatureWrapper;
import cucumber.api.testng.TestNGCucumberRunner;

@CucumberOptions(features = "./Features", glue = { "com.ibm.wce.scbn.cc.stepdefinitions" }, tags = { "@Sanity" }

)

public class Sanity {

    private TestNGCucumberRunner testNGCucumberRunner;
    private static final Logger logger = Logger.getLogger(Sanity.class.getName());

    @BeforeClass(alwaysRun = true)
    public void setUpClass() throws Exception {

        logger.info("initialize TestNG cucumber runner");
        testNGCucumberRunner = new TestNGCucumberRunner(this.getClass());
    }

    @Test(dataProvider = "features")
    public void feature(CucumberFeatureWrapper cucumberFeature) {
        logger.info("Running Cucumber features in loop");

        testNGCucumberRunner.runCucumber(cucumberFeature.getCucumberFeature());
    }

    @DataProvider
    public Object[][] features() {
        logger.info("inside data provider");

        return testNGCucumberRunner.provideFeatures();
    }

    @AfterClass(alwaysRun = true)
    public void tearDownClass() throws Exception {
        logger.info("close cucumber runner");

        testNGCucumberRunner.finish();
    }

}
Feature: Validating Mailbox response using Json data provider

  @Sanity
  Scenario: Validate Mailbox Bad Request response
    Given We have an ENDPOINT_baseURI "api.baseUrl"
    Given I set test report name "Mailbox API-Without required fields(Bad Request)"
    And We declare a new Request
    And We have Json request "bad_request" in file "api.mailboxJsonPayLoads"
    And We have below Header parameters
      | Content-Type | application/json |
    When We send post request to service "api.mailboxService"
    Then The response status code should be Bad Request
<suite name="Suite1">
    <test name="Sanity">
        <classes>
            <class name="com.ibm.wce.scbn.cc.runner.Sanity" />
        </classes>
    </test> <!-- Test -->
    <test name="Regression">
        <classes>
            <class name="com.ibm.wce.scbn.cc.runner.Regression" />
        </classes>
    </test> <!-- Test -->
</suite> <!-- Sanity1 -->

1

1 Answers

0
votes

Annotations cannot be parameterized.

If you would like to get this done, then there's a round about way of doing it.

Here are the steps that you need to follow

  1. You start off by having a class implement the annotation interface cucumber.api.CucumberOptions
  2. Make provisions in this class such that it can read the tags to be executed from a JVM argument and return it, when cucumber.api.CucumberOptions#tags is invoked.
  3. Build a TestNG listener that implements org.testng.IInvokedMethodListener
  4. Within this listener's beforeInvocation() method, you will get access to the test method and via it, its enclosing class. Retrieve the class object.
  5. On the retrieved class object, read and check if it has the annotation cucumber.api.CucumberOptions. If it has the annotation set, then you would need to use reflection to on the class, wherein you replace the original annotation object with the custom object that you created in (1)
  6. Wire in this listener into your suite file using the <listeners> tag or via the service provider mechanism.

That should take care of letting you accomplish your requirement.

Here are some code samples from one of my open source libraries I built, which leverages this concept.

  1. Implementing an annotation, see here.
  2. Wiring in your implementation via a TestNG listener, see here.
  3. Reflection utility that lets you change annotation values at run time, see here.
    1. Service Provider interface mechanism of wiring in the listener, see here.