Hot questions for Using Cucumber in picocontainer

Top Java Programmings / Cucumber / picocontainer

Question:

I'm currently working on a java test framework with cucumber, JUnit and Selenium. I've already worked on projects like that, but I'm experiencing an issue on this one.

I'm trying to create a Context class that is a Singleton. I want to use cucumber-picocontainer to have this class accessible in every step definition class. I added the dependencies in my pom.xml, but every time I try to execute my tests, I have an exception that says : "NewLoginSteps doesn't have an empty constructor. If you need DI, put cucumber-picocontainer on the classpath". I tried to import the jars manually, but it didn't help.

Here is a sample of my configuration :

  • pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <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/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
    
        <properties>
            <cucumber.version>1.2.4</cucumber.version>
            <selenium-java.version>2.39.0</selenium-java.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>info.cukes</groupId>
                <artifactId>cucumber-java</artifactId>
                <version>${cucumber.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>info.cukes</groupId>
                <artifactId>cucumber-picocontainer</artifactId>
                <version>${cucumber.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>info.cukes</groupId>
                <artifactId>cucumber-junit</artifactId>
                <version>${cucumber.version}</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
    </project>
    

TestContext.java :

public class TestContext {
    private static Map<String, String> siteLocations = new HashMap<String, String>();
    private static boolean initialized = false;
    private static boolean firstInitDone = false;
    private static WebDriver driver;
    private static boolean testsToRun = false;
    private static AutomatedTestMode modeAsEnum;

    @Before
    public void setUp(Scenario scenario) {
        initialize();
        Log.startTestCase(scenario.getName());
        afterAll();
    }
    ....
}

a step definition class :

public class NewLoginSteps extends NewSuperSteps {

    public NewLoginSteps(TestContext context){
        super(context);
    }


    @When("^I log in nova as \"([^\"]*)\" user with \"([^\"]*)\" \"([^\"]*)\"$")
    public void newLogin(String instance, String username, String password){
        Assert.assertEquals(true, false);

    }

    @Then("^The user is connected$")
    public void The_user_is_connected(){
        throw new PendingException();
    }

}

my superSepts class :

public class NewSuperSteps {
    protected TestContext context;
    public NewSuperSteps(TestContext context){
        this.context=context;
    }

}

Do you have an idea about what I've done wrong ? I've already used picocontainer in order to do the same thing and it was working.


Answer:

I faced similiar issue.

The problem was in the version of the info cukes..You need to have the same version of all cucumber-* in your pom.xml. That solved the issue for me.

Question:

I have used the accepted solution here and came up with the following code:

Referenced Libraries:

Feature:

Feature: FeatureA

  Scenario: ScenarioA
    Given 
    When 
    Then

  Scenario: ScenarioB
    Given 
    When 
    Then

BaseStep:

public class BaseStep {
    protected WebDriver driver = null;
    private static boolean isInitialized = false;

    @Before
    public void setUp() throws Exception {
        if (!isInitialized) {
            driver = SeleniumUtil.getWebDriver(ConfigUtil.readKey("browser"));
            isInitialized = true;
        }
    }

    @After
    public void tearDown() {
        driver.quit();
    }

}

StepA:

public class StepA {
    private BaseStep baseStep = null;
    private WebDriver driver = null;

    // PicoContainer injects BaseStep class
    public StepA(BaseStep baseStep) {
        this.baseStep = baseStep;
    }

    @Given("^I am at the Login page$")
    public void givenIAmAtTheLoginPage() throws Exception {
        driver = baseStep.driver;
        driver.get(ConfigUtil.readKey("base_url"));
    }

    @When
    @When
    @Then
    @Then

}

However, the driver "dies" after tearDown() of ScenarioA and becomes null on Given step of ScenarioB (both scenarios use the same Given). I am not using Maven.


Answer:

It's because of this line:

private static boolean isInitialized = false;

For each scenario, cucumber creates a new instance for every step file involved. Hence, the driver in BaseStep is always null when a scenario starts.

The static isInitialized boolean is not part of an instance, it's bound to the class it lives in and it's alive until the JVM shuts down. The first scenario sets it to true, meaning that when the second scenario starts it's still true and it does not reinitialize the driver in the setUp() method.

You probably want to make driver static to share the same instance with both scenarios.

Question:

I'm experiencing the same situation as this question, but none of the suggested solutions work for me. Basically, I have taken a download of this repository. It runs fine. Then, I have split the SearchSteps module into two - one that contains the @Before and @After statement, and one that contains the steps (as I intend to reuse the initialisation code). I have added the dependency on cucumber-picocontainer to my pom.xml.

I am getting the same error as in the question above: class com.browserstack.stepdefs.SearchSteps doesn't have an empty constructor. If you need DI, put cucumber-picocontainer on the classpath. I've tried all of the suggested solutions but the error remains.

My pom.xml looks as follows:

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.browserstack</groupId>
    <artifactId>cucumber-jvm-java-browserstack</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>cucumber-jvm-java-browserstack</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <cucumber.jvm.parallel.version>2.2.0</cucumber.jvm.parallel.version>
        <surefire.maven.plugin.version>2.19.1</surefire.maven.plugin.version>
        <acceptance.test.parallel.count>1</acceptance.test.parallel.count>
    </properties>

    <dependencies>

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>1.2.5</version>
        </dependency>

        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>1.2.5</version>
        </dependency>

        <dependency>
            <groupId>org.picocontainer</groupId>
            <artifactId>picocontainer</artifactId>
            <version>2.14.3</version>
        </dependency>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.0.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>com.browserstack</groupId>
            <artifactId>browserstack-local-java</artifactId>
            <version>1.0.1</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${surefire.maven.plugin.version}</version>
                <executions>
                    <execution>
                        <id>acceptance-test</id>
                        <phase>integration-test</phase>
                        <goals>
                            <goal>test</goal>
                        </goals>
                        <configuration>
                            <forkCount>${acceptance.test.parallel.count}</forkCount>
                            <reuseForks>true</reuseForks>
                            <includes>
                                <include>**/*IT.class</include>
                            </includes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.0.2</version>
                <executions>
                    <execution>
                        <id>copy-resources</id>
                        <!-- here the phase you need -->
                        <phase>validate</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>target/test-classes/com/yourcompany/cucumberjvm</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>src/test/resources</directory>
                                    <filtering>true</filtering>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>com.github.temyers</groupId>
                <artifactId>cucumber-jvm-parallel-plugin</artifactId>
                <version>${cucumber.jvm.parallel.version}</version>
                <executions>
                    <execution>
                        <id>generateRunners</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>generateRunners</goal>
                        </goals>
                        <configuration>
                            <!-- Mandatory -->
                            <!-- comma separated list of package names to scan for glue code -->
                            <glue>com.browserstack.stepdefs</glue>
                            <!-- These are the default values -->
                            <!-- Where to output the generated Junit tests -->
                            <outputDirectory>${project.build.directory}/generated-test-sources/features</outputDirectory>
                            <!-- The diectory containing your feature files.  -->
                            <featuresDirectory>src/test/java/resources/features</featuresDirectory>
                            <cucumberOutputDir>${project.build.directory}/cucumber_reports/test_results</cucumberOutputDir>
                            <!-- comma separated list of output formats -->
                            <format>junit</format>
                            <!-- CucumberOptions.strict property -->
                            <strict>true</strict>
                            <!-- CucumberOptions.monochrome property -->
                            <monochrome>true</monochrome>
                            <!-- The tags to run, maps to CucumberOptions.tags property -->
                            <tags>"~@ignore"</tags>

                            <namingScheme>pattern</namingScheme>
                            <!-- The class naming pattern to use.  Only required/used if naming scheme is 'pattern'.-->
                            <namingPattern>{f}_Parallel{c}IT</namingPattern>

                            <!-- If set to true, only feature files containing the required tags shall be generated. -->
                            <!-- Excluded tags (~@notMe) are ignored. -->
                            <filterFeaturesByTags>true</filterFeaturesByTags>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

The dependency shows in my project structure. What am I doing wrong?

Happy to provide all source code if required.


Answer:

The answer given by @mpkorstanje above is correct. The full text of the dependency is as follows, notice the same version as all the info.cukes artifacts:

<dependency>
   <groupId>info.cukes</groupId>
   <artifactId>cucumber-picocontainer</artifactId>
   <version>1.2.5</version>
</dependency>

Question:

Hi everybody: I'm creating a repository in Maven with Cucumber, Selenium, TestNG.

What I'm trying to do is getting the values from a properties file for sending these parameters with Selenium, but I cannot reach with the solution to the issues generated here.

This is the structure of my project:

    .
├── pom.xml
├── selenium_cucumber.iml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── utilities
│   │   │       ├── LoadProperties.java
│   │   │       └── ReportMerger.java
│   │   └── resources
│   │       ├── config.properties
│   │       └── log4j.properties
│   └── test
│       ├── java
│       │   ├── features
│       │   │   └── first.feature
│       │   ├── hooks
│       │   │   ├── ServiceHooks.java
│       │   │   ├── TakesScreenshots.java
│       │   │   └── WebDriverManager.java
│       │   ├── pages
│       │   │   ├── BasePage.java
│       │   │   └── Page_First.java
│       │   ├── runners
│       │   │   └── testNGCucumberRunner.java
│       │   └── steps
│       │       └── Step_First.java
│       └── resources
│           └── testng.xml
└── target

This is my feature file:

@test
Feature: Navigation Test
  This is example of using Cucumber-JVM with TestNG and Selenium


  Scenario: Search google.com to verify google search is working

    Given I go to "<Url>" Google
    When I query for "<search>" cucumber spring selenium
    And click search
    Then google page title should become the first page

Continue with the page that load the properties from a properties file (config.properties)

package utilities;

import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;


public class LoadProperties {

    Properties prop;

    public LoadProperties(){

        try{
            prop = new Properties();

            File fis = new File("src/main/resources/config.properties");

            FileInputStream input = new FileInputStream(fis);

            prop.load(input);
        }
        catch(Exception e){
            System.out.println("Error loading configuration file");
        }
    }

    public String getUrl()
    {
        return prop.getProperty("Url");
    }

    public String getNavigator(){

        return prop.getProperty("navigator");
    }

    public String searchData(){

        return prop.getProperty("search");
    }

}

The config.properties file:

navigator = "firefox"
Url = "https://www.google.com"
search = "cucumber spring selenium"

Very important to mention that I'm using the API WebdriverManager (By Boni Garcia), because with this it is not necessary put the drivers of each browser in a folder and download them.

package hooks;

import com.codeborne.selenide.WebDriverRunner;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.opera.OperaDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;

    @Component
    public class WebDriverManager {

        private WebDriver webDriver;


        public WebDriver getDriver() {
            return webDriver;
        }

        @Bean(destroyMethod = "quit")
        public WebDriver getWebDriver(){
            String currentWebDriver = System.getProperty("browser", "");
            switch(currentWebDriver) {
                case ("chrome"):
                    System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
                    webDriver = new ChromeDriver();
                    break;
                case ("firefox"):
                    System.setProperty("webdriver.gecko.driver", "geckodriver.exe");
                    FirefoxOptions firefoxOptions = new FirefoxOptions();
                    firefoxOptions.setCapability("marionette", true);
                    webDriver = new FirefoxDriver(firefoxOptions);
                    break;
                case ("chromeHeadless"):
                    System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
                    ChromeOptions chromeHeadless = new ChromeOptions();
                    chromeHeadless.setHeadless(true);
                    webDriver = new ChromeDriver(chromeHeadless);
                    break;
                case ("iexplorer"):
                    System.setProperty("webdriver.ie.driver", "IEDriverServer.exe");
                    DesiredCapabilities capabilitiesIE = DesiredCapabilities.internetExplorer();
                    capabilitiesIE.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
                    webDriver = new InternetExplorerDriver(capabilitiesIE);
                    break;
                case ("edge"):
                    System.setProperty("webdriver.edge.driver", "MicrosoftWebDriver.exe");
                    webDriver = new EdgeDriver();
                    break;
                case ("opera"):
                    System.setProperty("webdriver.opera.driver", "operadriver.exe");
                    webDriver = new OperaDriver();
                    break;
                default:
                    System.getProperty("browser", "chrome");
                    System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
                    webDriver = new ChromeDriver();
                    break;
            }

            //Using Selenide driver:
            WebDriverRunner.setWebDriver(webDriver);
            return webDriver;
        }

        @PreDestroy
        public void closeSession(){
            getDriver().manage().deleteAllCookies();
            getDriver().close();
            getDriver().quit();
        }
}

By other hand I'm working with Page Factory, this is the Common Base Page for working with:

package pages;

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

public abstract class BasePage {

    private WebDriver driver ;
    private static final Logger log = Logger.getLogger(BasePage.class.getName());

    //Constructor
    public BasePage(WebDriver driver){

        this.driver = driver;
        this.driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        this.driver.manage().window().maximize();
        this.driver.getTitle();

        log.info("______________________Starting tests______________________");
    }

    public String getPageTitle(){
        return driver.getTitle();
    }

    public Logger getLOG() {
        return log;
    }


    public void navigate(String Url){
        driver.get(Url);
    }

/*
    public abstract boolean isAt();
*/

    //Methods

    protected void waitForElementClickable(WebElement element){
        WebDriverWait wait = new WebDriverWait(driver, 30);
        wait.until(ExpectedConditions.elementToBeClickable(element));
    }

    protected void waitForElementVisible(WebElement element){
        WebDriverWait wait = new WebDriverWait(driver, 15);
        wait.until(ExpectedConditions.visibilityOf(element));
    }

    protected void setTextAs(WebElement element, String text) throws IOException {
        waitForElementClickable(element);
        element.sendKeys((text));
    }

    protected void clearElement(WebElement element){
        waitForElementClickable(element);
        element.clear();
    }

    protected void clickElement(WebElement element){
        waitForElementClickable(element);
        element.click();
    }

    protected void clickElementByJavascriptExecutor(String xpath){
        WebElement element=driver.findElement(By.xpath(xpath));
        JavascriptExecutor ex=(JavascriptExecutor)driver;
        ex.executeScript("arguments[0].click()", element);
    }

    protected void clickLink(WebElement element){
        waitForElementVisible(element);
        element.click();
    }

    protected String getText(WebElement element){
        waitForElementVisible(element);
        return element.getText();
    }


    protected void freeze(int seconds) {
        try {
            Thread.sleep(seconds * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Don't we forget about a Test Runner Class (testNGCucumberRunner)

package runners;

import cucumber.api.CucumberOptions;
import cucumber.api.testng.CucumberFeatureWrapper;
import cucumber.api.testng.PickleEventWrapper;
import cucumber.api.testng.TestNGCucumberRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

@CucumberOptions(
        plugin = {"pretty","json:target/report/cucumber2.json", "html:target/cucumber-reports"},
        strict = true,
        features = {"src/test/java/features"},
        tags = {"@test"},
        glue = {"steps"}
)
    public class testNGCucumberRunner {
    private static final Logger LOG = LoggerFactory.getLogger(runners.testNGCucumberRunner.class);
    private TestNGCucumberRunner testNGCucumberRunner;

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

    @Test(groups = "Cucumber", description = "Runs Cucumber Feature", dataProvider = "scenarios")
    public void scenario(PickleEventWrapper pickleEvent, CucumberFeatureWrapper cucumberFeature) throws Throwable {
        LOG.info("STARTING THIS FEATURE >>>>>" + cucumberFeature + "<<<<<<<<<<<<<<<<<<<<<<<<<<");
        testNGCucumberRunner.runScenario(pickleEvent.getPickleEvent());
    }

    @DataProvider
    public Object[][] scenarios() {
        return testNGCucumberRunner.provideScenarios();
    }

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

Also the Hooks class is present here (ServiceHooks)

package hooks;

import cucumber.api.Scenario;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import static com.codeborne.selenide.WebDriverRunner.getWebDriver;

public class ServiceHooks {

    private static final Logger log = LoggerFactory.getLogger(ServiceHooks.class);
    private WebDriver webDriver;

    @Before
    public void setUpBrowser(Scenario scenario) throws Exception {

        log.info("****************************************************************************************");
        log.info("$$$$$$$$$$$$$$$$$$$$$ Start of execution of scenario with name: " + scenario.getName() + "    $$$$$$$$$$$$$$$$$$$$$$$");
        log.info("****************************************************************************************");

        if (webDriver == null) {
            log.error("WebDriver did not initialize correctly");
        }
    }

    @After
    public void tearDown(Scenario scenario) throws Exception {
        WebDriver driver = getWebDriver();
        log.info("****************************************************************************************");
        log.info("$$$$$$$$$$$$$$$$$$$$$ Completion of execution of scenario with name: " + scenario.getName() + "    $$$$$$$$$$$$$$$$$$$$$$$");
        log.info("****************************************************************************************");
        if (scenario.isFailed()) {
            log.info("****************************************************************************************");
            log.info("$$$$$$$$$$$$$$$$$$$$$ Failing scenario with name: " + scenario.getName() + "    $$$$$$$$$$$$$$$$$$$$$$$");
            log.info("****************************************************************************************");
            try {
                byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
                scenario.embed(screenshot, "image/png");
            } catch (WebDriverException somePlatformsDontSupportScreenshots) {
                System.err.println(somePlatformsDontSupportScreenshots.getMessage());
            }
        }
        driver.quit();
        log.info("Driver closed");
    }
}

My POM cannot be forgotten here:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>automation</groupId>
    <artifactId>selenium_cucumber</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.version>3.7.0</maven.compiler.version>
        <cucumber.version>3.0.2</cucumber.version>
        <selenium.version>3.12.0</selenium.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-core</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java8 -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java8</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-picocontainer -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-picocontainer</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-testng -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-testng</artifactId>
            <version>${cucumber.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>3.8.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.codeborne/selenide -->
        <dependency>
            <groupId>com.codeborne</groupId>
            <artifactId>selenide</artifactId>
            <version>5.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.5</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

My testng.xml file is the next:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Google Suite" verbose="1" thread-count="1" parallel="tests" configfailurepolicy="continue">
    <test name="Google UI automation">
        <classes>
            <class name="runners.testNGCucumberRunner">
                <methods>
                    <include name="scenario"/>
                </methods>
            </class>
        </classes>
    </test>
</suite>

The Page related with the feature named before is the next:

package pages;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

import java.io.IOException;

public class Page_First extends BasePage{

    /////////////Constructor/////////////

    public Page_First(WebDriver driver) {
        super(driver);
    }

    //////////////////////////////////////////////WEB ELEMENTS//////////////////////////////////////////////////////////

    @FindBy(name = "q")
    private WebElement searchText;

    @FindBy(name="btnK")
    private WebElement searchButton;

    //////////////////////////////////////////////BASE METHODS//////////////////////////////////////////////////////////

    public void search(String search) throws IOException {
        setTextAs(searchText, search);
    }

    public void enterButton (){
        clickElement(searchButton);
    }
}

And the step definitions class related with this is the next one:

package steps;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.PageFactory;
import pages.BasePage;
import pages.Page_First;
import utilities.LoadProperties;

import java.io.IOException;
import java.util.logging.Logger;

public class Step_First {

    private WebDriver driver;
    private BasePage basepage;


    private Page_First page_first = PageFactory.initElements(driver, Page_First.class);


    private static final java.util.logging.Logger log = Logger.getLogger(Page_First.class.getName());
    LoadProperties load = new LoadProperties();


    public Step_First(WebDriver driver){

        this.driver = driver;
    }


    @Given("I go to {string} Google")
    public void I_go_to_Google (String Url) {

        load.getUrl();
    //    basepage.navigate(Url);
    }

    @When("I query for {string} cucumber spring selenium")
    public void I_query_for_cucumber_spring_selenium (String search) throws IOException {

        page_first.search(search);
    }

    @When("click search")
    public void click_search(){

        page_first.enterButton();
    }

    @Then("google page title should become the first page")
    public void google_page_title_should_become_the_first_page() {

        log.info("All OK");

    }
}

After all this information and classes and more classes, I really don't know where I'm failing, because when I run the testNGCucumberRunner class from the IDE (IntelliJ IDEA) I'm getting the next error in console:

    @test
  Scenario: Search google.com to verify google search is working # src/test/java/features/first.feature:6
    Given I go to "<Url>" Google                                 # Step_First.I_go_to_Google(String)
      org.picocontainer.injectors.AbstractInjector$UnsatisfiableDependenciesException: steps.Step_First has unsatisfied dependency 'interface org.openqa.selenium.WebDriver' for constructor 'public steps.Step_First(org.openqa.selenium.WebDriver)' from org.picocontainer.DefaultPicoContainer@4c12331b:1<|
    at org.picocontainer.injectors.ConstructorInjector.getGreediestSatisfiableConstructor(ConstructorInjector.java:191)
    at org.picocontainer.injectors.ConstructorInjector.getGreediestSatisfiableConstructor(ConstructorInjector.java:110)
    at org.picocontainer.injectors.ConstructorInjector.access$100(ConstructorInjector.java:51)
    at org.picocontainer.injectors.ConstructorInjector$1.run(ConstructorInjector.java:331)
    at org.picocontainer.injectors.AbstractInjector$ThreadLocalCyclicDependencyGuard.observe(AbstractInjector.java:270)
    at org.picocontainer.injectors.ConstructorInjector.getComponentInstance(ConstructorInjector.java:364)
    at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.getComponentInstance(AbstractInjectionFactory.java:56)
    at org.picocontainer.behaviors.AbstractBehavior.getComponentInstance(AbstractBehavior.java:64)
    at org.picocontainer.behaviors.Stored.getComponentInstance(Stored.java:91)
    at org.picocontainer.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:699)
    at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:647)
    at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:678)
    at cucumber.runtime.java.picocontainer.PicoFactory.getInstance(PicoFactory.java:40)
    at cucumber.runtime.java.JavaStepDefinition.execute(JavaStepDefinition.java:48)
    at cucumber.runtime.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:50)
    at cucumber.runner.TestStep.executeStep(TestStep.java:55)
    at cucumber.runner.TestStep.run(TestStep.java:42)
    at cucumber.runner.PickleStepTestStep.run(PickleStepTestStep.java:53)
    at cucumber.runner.TestCase.run(TestCase.java:47)
    at cucumber.runner.Runner.runPickle(Runner.java:44)
    at cucumber.api.testng.TestNGCucumberRunner.runScenario(TestNGCucumberRunner.java:56)
    at runners.testNGCucumberRunner.scenario(testNGCucumberRunner.java:33)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:583)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:719)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:989)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
    at org.testng.TestRunner.privateRun(TestRunner.java:648)
    at org.testng.TestRunner.run(TestRunner.java:505)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
    at org.testng.SuiteRunner.run(SuiteRunner.java:364)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
    ...
    at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
    at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:110)
    at ✽.I go to "<Url>" Google (src/test/java/features/first.feature:8)

I think is something related with picocontainer dependency (Included in my POM), but I cannot reach the failing issue.

Failed scenarios:
src/test/java/features/first.feature:6 # Search google.com to verify google search is working

1 Scenarios (1 failed)
4 Steps (1 failed, 3 skipped)
0m0.071s

org.picocontainer.injectors.AbstractInjector$UnsatisfiableDependenciesException: steps.Step_First has unsatisfied dependency 'interface org.openqa.selenium.WebDriver' for constructor 'public steps.Step_First(org.openqa.selenium.WebDriver)' from org.picocontainer.DefaultPicoContainer@4c12331b:1<|
    at org.picocontainer.injectors.ConstructorInjector.getGreediestSatisfiableConstructor(ConstructorInjector.java:191)
    at org.picocontainer.injectors.ConstructorInjector.getGreediestSatisfiableConstructor(ConstructorInjector.java:110)
    at org.picocontainer.injectors.ConstructorInjector.access$100(ConstructorInjector.java:51)
    at org.picocontainer.injectors.ConstructorInjector$1.run(ConstructorInjector.java:331)
    at org.picocontainer.injectors.AbstractInjector$ThreadLocalCyclicDependencyGuard.observe(AbstractInjector.java:270)
    at org.picocontainer.injectors.ConstructorInjector.getComponentInstance(ConstructorInjector.java:364)
    at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.getComponentInstance(AbstractInjectionFactory.java:56)
    at org.picocontainer.behaviors.AbstractBehavior.getComponentInstance(AbstractBehavior.java:64)
    at org.picocontainer.behaviors.Stored.getComponentInstance(Stored.java:91)
    at org.picocontainer.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:699)
    at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:647)
    at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:678)
    at cucumber.runtime.java.picocontainer.PicoFactory.getInstance(PicoFactory.java:40)
    at cucumber.runtime.java.JavaStepDefinition.execute(JavaStepDefinition.java:48)
    at cucumber.runtime.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:50)
    ...
    at cucumber.api.testng.TestNGCucumberRunner.runScenario(TestNGCucumberRunner.java:56)
    at runners.testNGCucumberRunner.scenario(testNGCucumberRunner.java:33)
    ...
    at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:110)
    at ✽.I go to "<Url>" Google (src/test/java/features/first.feature:8)



===============================================
Default Suite
Total tests run: 1, Failures: 0, Skips: 1
===============================================

May anybody help me with this? Thanks in advance.


Answer:

I agree with the above answer. As a better solution, use a 'Test Context' class to store all required objects while swapping multiple step classes.

Test Context class can store:

  • WebDriver object,
  • page objects,
  • DataReader object, etc.

Use a pageobject manager to keep page classes. Below is a code segment in the pageobject manager class.

private HomePage;  
public HomePage getHomePage(){
      return (homePage == null) ? homePage = new HomePage(driver) : homePage;
      }

Please refer to this too. https://cucumber.io/blog/bdd/polymorphic-step-definitions/