Search code examples
cucumbertestngcucumber-java

Cucumber execution with TestNG - There were undefined steps


I wanted to run my cucumber features with TestNG for parallel execution. I continue to keep on running into the issue where testNG fails to find the matching glue code. Although the code is written and mapped correctly with Steps.

Test Execution is skipped and error states that There were undefined steps that needs to be defined. I then moved the Step Definitions class into the same package where my Test Runner class was, and the execution went on successfully.

I fail to understand that why testNG is not able to recognize the glue code in different package. I tried to work on different dependencies as well but that didn't worked as well. Is there any other way to make sure testNG looks at the right place for step definitions ?

Below is the POM :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>CucumberPractice</groupId>
  <artifactId>CucumberPractice</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>CucumberPractice</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-core</artifactId>
    <version>4.7.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java -->
<dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-java</artifactId>
    <version>4.7.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-junit -->
<dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-junit</artifactId>
    <version>4.7.2</version>
    <scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-jvm-deps -->
<dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-jvm-deps</artifactId>
    <version>1.0.6</version>
    <scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hamcrest/hamcrest-core -->
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-core</artifactId>
    <version>2.1</version>
    <scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.59</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/gherkin -->
<dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>gherkin</artifactId>
    <version>5.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-html -->
<dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-html</artifactId>
    <version>0.2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <version>1.10.19</version>
    <scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-testng -->
<dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-testng</artifactId>
    <version>4.7.2</version>
</dependency>
</dependencies>
</project>

Below is the Step Definition class :

package CucumberPageLogic;

import java.util.Set;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;

import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import junit.framework.Assert;



public class PageLogic {

    public WebDriver driver;
    public WebDriverWait wait;

    @Before("@Chrome")
    public void driverSetup() {
        System.out.println("In Before");
        System.setProperty("webdriver.chrome.driver", "driverPath");
        driver= new ChromeDriver();
        wait= new WebDriverWait(driver,20);
    }

    @After
    public void tearDown() {
        driver.quit();
    }
    @Given("User opens Salesforce.com")
    public void userOpensSalesforceCom() {
       driver.get("https://www.salesforce.com/in/?ir=1");
       driver.manage().window().maximize();
    }

    @Given("Home Page is sucessfully loaded")
    public void homePageIsSucessfullyLoaded() {
       wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div[@class='btn-container hidden-xs']//span[contains(text(),'Try')]")));
    }

    @When("User clicks on Try For Free button")
    public void userClicksOnTryForFreeButton() {
        wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div[@class='btn-container hidden-xs']//span[contains(text(),'Try')]"))).click();
    }

    @When("^User enters SignUp \"(.*)\" \"(.*)\" \"(.*)\" information$")
    public void userEntersSignUpInformation(String firstname, String lastname, String jobtitle) {
       driver.findElement(By.name("UserFirstName")).sendKeys(firstname);
       driver.findElement(By.name("UserLastName")).sendKeys(lastname);
       Select select = new Select(driver.findElement(By.name("UserTitle")));
       select.selectByVisibleText(jobtitle); 
    }


    @Then("New Tab is opened")
    public void newTabIsOpened() {
        Set<String> handles = driver.getWindowHandles();
        if(handles.isEmpty()) {
            Assert.fail();
        }

        System.out.println("these are the handles :"+handles);
        System.out.println("Current Handle :"+driver.getWindowHandle());
        for(String handle:handles) {
            if(!handle.equals(driver.getWindowHandle())) {
                    System.out.println("Switching to "+handle);
                    driver.switchTo().window(handle);
                    break;
                }
        }

    }

    @Then("User goes back to home page")
    public void userGoesBackToHomeTab() {
        Set<String> handles = driver.getWindowHandles();
        if(handles.isEmpty()) {
            Assert.fail();
        }
        System.out.println("these are the handles :"+handles);
        System.out.println("Current Handle :"+driver.getWindowHandle());
        for(String handle:handles) {
            if(!handle.equals(driver.getWindowHandle())) {
                System.out.println("Switching to "+handle);
                    driver.switchTo().window(handle);
                    break;
                }
        }
    }

    @Then("Sign up form is visible")
    public void signUpFormIsVisible() {
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.name("UserFirstName")));
    }

    @Then("validate home page content")
    public void validateHomePageContent() {
        wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div[@class='btn-container hidden-xs']//span[contains(text(),'Try')]")));
    }

}

Below is the Test Runner Class :

package CucumberPractice;

import org.testng.annotations.DataProvider;
import io.cucumber.junit.CucumberOptions;
import io.cucumber.junit.CucumberOptions.SnippetType;
import io.cucumber.testng.AbstractTestNGCucumberTests;

//@RunWith(Cucumber.class)


@CucumberOptions(features= {"C:\\Users\\komehta\\eclipse-workspace\\CucumberPractice\\src\\test\\java\\CucumberPractice"},
        dryRun=false,
        glue= {"CucumberPageLogic"},
        snippets= SnippetType.CAMELCASE,
        tags= {"@NewTabFeature"},
        strict=false,
         plugin= {
                    "pretty","html:test-outout", 
                    "json:json_output/cucumber.json", 
                    "junit:junit_xml/cucumber.xml"
                })


public class CucumberTestRunner extends AbstractTestNGCucumberTests  {
    @Override
    @DataProvider(parallel = true)
    public Object[][] scenarios() {
        return super.scenarios();
    }
}

Feature File :

@NewTabFeature @Chrome
Feature: Opening the WebPage in New Tab


  @NewTabSnr1
  Scenario: Open the link in a New WebPage and Validate the Content
    Given User opens Salesforce.com
    And Home Page is sucessfully loaded
    When User clicks on Try For Free button
    Then New Tab is opened
    And Sign up form is visible

  @NewTabSnr2
  Scenario Outline: Validate the Content on HomePage after entering details on new tab
    Given User opens Salesforce.com
    And Home Page is sucessfully loaded
    When User clicks on Try For Free button
    And New Tab is opened
    And User enters SignUp "<firstname>" "<lastname>" "<jobtitle>" information
    Then User goes back to home page
    And validate home page content

    Examples: 
      | firstname | lastname | jobtitle  |
      | Kovid |Mehta | Sales Manager |
      | Vikas |Bhat | IT Manager |

Solution

  • If you remove dependencies you don't use or pull in transitively and let Maven do the dependency management for you you'll see that you have to replace:

    import io.cucumber.junit.CucumberOptions;
    import io.cucumber.junit.CucumberOptions.SnippetType;
    

    with:

    import io.cucumber.testng.CucumberOptions;
    import io.cucumber.testng.CucumberOptions.SnippetType;
    

    Currently you can remove:

    junit
    cucumber-junit
    cucumber-jvm-dep
    gherkin
    cucumber-html