Cucumber - Java8 - using @Before with lambda expressions

Hester Lyons :

I have a Java selenium project set up using cucumber. Step definitions are in a set of files that reuse code from a BaseDefinitions file, as follows:

(Example curtailed to first @Given statement):

public class GoogleDefinitions {

    private BaseDefinitions baseDefinitions;
    private WebDriver driver;

    public GoogleDefinitions (BaseDefinitions baseDefinitions) {
        this.baseDefinitions = baseDefinitions;
        this.driver = baseDefinitions.getDriver();
    }

    @Given("^I visit the Google search page$")
    public void iVisitTheGoogleSearchPage() {
        GoogleSearchHomepage googleSearchHomepage = new GoogleSearchHomepage(driver);
        googleSearchHomepage.visit();
    }
}

The BaseDefinitions file (short version) looks as follows:

public class BaseDefinitions {

    private WebDriver driver;


    @Before
    public void setUp(Scenario scenario) throws Exception {
        String path = getClass()
                .getClassLoader()
                .getResource("chromedriver.exe")
                .getPath();
        System.setProperty("webdriver.chrome.driver", path);
        driver = new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    }

    @After
    public void teardown() {
        driver.close();
        try {
            driver.quit();
        }
        catch(Exception e) {
            System.out.println("Caught driver error on quit.");
        }
    }

    public WebDriver getDriver() {
        return driver;
    }
}

This works fine - glue code etc is all set up correctly. However, with updates, Cucumber is now generating lambda expressions rather than the format used before. I am confused as to how to implement these.

  • If I implement them in the constructor (as discussed here), then the @Before statement of the BaseDefinitions file is only executed after the test when I run the feature - this is of no use.
  • If I put them in a method, as shown here, when I run the feature file it runs the @Before statement but does not find the step definitions.

Below is an example with the lambdas implemented in a method. When I run this it gives me You can implement missing steps with the snippets below::

public class lambdaTestDefinitions implements En {
    private BaseDefinitions baseDefinitions;
    private WebDriver driver;

    public lambdaTestDefinitions(BaseDefinitions baseDefinitions) {
        this.baseDefinitions = baseDefinitions;
        this.driver = baseDefinitions.getDriver();
    }

    private void testLambdaSteps () {
        Given("I try to navigate to www.google.co.uk", () -> {
            driver.get("http://www.google.co.uk");
        });

        Then("I should be on the Google home page", () -> {
            // Write code here that turns the phrase above into concrete actions
            Assert.assertEquals(driver.getCurrentUrl(), "http://www.google.co.uk");
        });
    }
}

Clearly I am missing something - how do I get this to work?

EDIT: Here is my build.gradle. From what I can see I am not using the Java8 version of Cucumber, which I don't really understand either:

buildscript {
    repositories {
        mavenCentral()
    }
}

plugins {
    id 'java'
    //id "com.github.spacialcircumstances.gradle-cucumber-reporting" version "0.1.2"
}

group 'org.myorg'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
    jcenter()
}

project.ext {
    cucumberVersion = '4.0.0'
}

dependencies {
    compile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.5.1'
    testCompile group: 'junit', name: 'junit', version: '4.12'
    testCompile 'io.cucumber:cucumber-java:' + cucumberVersion
    testCompile 'io.cucumber:cucumber-junit:' + cucumberVersion
    testCompile group: 'com.browserstack', name: 'browserstack-local-java', version:'1.0.1'
    testCompile group: 'io.cucumber', name: 'cucumber-picocontainer', version: '2.1.0'
    testCompile group: 'org.hamcrest', name: 'hamcrest-all', version: '1.3'
    testCompile group: 'org.testng', name: 'testng', version: '6.9.10'
    testCompile 'io.github.prashant-ramcharan:courgette-jvm:3.1.0'
}

test {
    systemProperties System.getProperties()
    ignoreFailures = true

    systemProperty "localBrowser", System.getProperty("localBrowser")
    systemProperty "browserstackLocal", System.getProperty("browserstackLocal")
    systemProperty "browser", System.getProperty("browser")
    testLogging.showStandardStreams = true

    test.outputs.upToDateWhen {false}
}
mpkorstanje :

This works fine - glue code etc is all set up correctly. However, with updates, Cucumber is now generating lambda expressions rather than the format used before.

You've added cucumber-java8 instead of cucumber-java to your dependencies.

If I put them in a method, as shown here, when I run the feature file it runs the @Before statement but does not find the step definitions.

That only works for some frameworks that extend Cucumber. The eclipse plugin however supports both notations.

If I implement them in the constructor (as discussed here), then the @Before statement of the BaseDefinitions file is only executed after the test when I run the feature - this is of no use.

You are confusing the execution of the cucumber steps with the creation of the step definition. The creation of the step definition happens before any steps are invoked on it. this.driver = baseDefinitions.getDriver(); is called when creating GoogleDefinitions so always before the method that creates the driver.

Instead you should delay the call until the step is invoked.

public class lambdaTestDefinitions implements En {
    public lambdaTestDefinitions(BaseDefinitions baseDefinitions) {

        Given("I try to navigate to www.google.co.uk", () -> {
            baseDefinitions.getDriver().get("http://www.google.co.uk");
        });

        Then("I should be on the Google home page", () -> {
            // Write code here that turns the phrase above into concrete actions
            assertEquals(baseDefinitions.getDriver().getCurrentUrl(), "http://www.google.co.uk");
        });
    }
}

You may also be interested in investigating the PicoContainers life cycle. You can use Startable and Disposable. They can help you setup things that need to be setup before Cucumber starts a scenario.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=152739&siteId=1