Skip to content

Latest commit

 

History

History
237 lines (183 loc) · 7.77 KB

v7.0.0.md

File metadata and controls

237 lines (183 loc) · 7.77 KB

Cucumber-JVM v7.0.0

Another year, another major version.

Below we'll discuss some notable changes in v7.0.0 As always the full change log can be found in the usual place.

Cucumber Expressions v11

Prior to v11 Cucumber Expressions were transformed into regular expressions using a string substitution algorithm. This algorithm had a number of edge cases.

Starting with v11 the Cucumber Expressions are described by their own grammar. This fixes various ambiguities and bugs in the way Cucumber expressions are parsed and transformed into regular expressions. This may however also break Cucumber Expressions that depend on these ambiguities.

Before-All and After-All Hooks

The Cucumber-Java module now supports before-all and after-all hooks. This closes one of the longest-open issues our issue tracker.

The hooks have 'invoke around' semantics. All before-hooks will be executed before any scenario is executed. After all scenarios have been executed all after-hooks will be executed.

package io.cucumber.example;

import io.cucumber.java.AfterAll;
import io.cucumber.java.BeforeAll;

public class StepDefinitions {

    @BeforeAll
    public static void beforeAll() {
        // Runs before all scenarios
    }

    @AfterAll
    public static void afterAll() {
        // Runs after all scenarios
    }
}

JUnit 5.8 / JUnit Platform 1.8

The CucumberJUnit Platform Engine has been updated to 1.8. With JUnit 5.8 comes the junit-platform-suite engine. This engine allows the programmatic declaration of test suites.

So it is now possible to write the following JUnit 4 test:

package com.example;

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(glue = "com.example.application", features = "classpath:com/example/application")
public class RunCucumberTest {

}

As a declarative JUnit 5 test suite:

package com.example;

import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;

import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;

@Suite
@IncludeEngines("cucumber")
@SelectPackages("com.example.application")
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.example.application")
public class RunCucumberTest {

}

In combination with the before-all and after-all hooks this allows for a feature-complete migration from JUnit 4.

Unfortunately Gradle and Surefire still only provide limited support for file based tests. While Cucumber tests can be executed, the results are reported in a <Class Name> - <Method Name> format. As a result only scenario names or example numbers are reported. This can make for hard to read reports.

By using cucumber.junit-platform.naming-strategy=long Cucumber will include the feature name in the scenario name. This makes the test results legible.

e.g for Maven:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M5</version>
    <configuration>
        <properties>
            <configurationParameters>
                cucumber.junit-platform.naming-strategy=long
            </configurationParameters>
        </properties>
    </configuration>
</plugin>

or for Gradle:

tasks.test {
    useJUnitPlatform()
    systemProperty("cucumber.junit-platform.naming-strategy", "long")
}

Finally, the @Cucumber annotation has been deprecated in favour of @Suite. The @Cucumber annotated class was originally intended as a workaround for both JUnit 5's lack of suites and Gralde and Surefires inability to discover non-class based. The with the introduction of the junit-platform-suite the @Suite annotation can do both.

Bill of Materials

It's a Bill of Materials (BOM) to help keep all dependencies aligned.

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-bom</artifactId>
            <version>${cucumber.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<!--Then for example-->

<dependencies>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-java</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-junit-platform-engine</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Support for properties in testng.xml

The AbstractTestNGCucumberTests will now pick up properties from testng.xml. This allows the same runner to be reused in multiple suites. For example:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Example Suite">
	<parameter name="cucumber.filter.tags" value="@Gherkin and not @Zucchini" />

	<test name="Vegetable garden" preserve-order="true">
        <parameter name="cucumber.features" value="classpath:com/example/features/vegetable"/>
		<parameter name="cucumber.glue" value="com.example.vegetables.glue"/>
		<classes>
			<class name="com.example.RunCucumberTests"/>
		</classes>
	</test>

	<test name="Herb garden" preserve-order="true">
		<parameter name="cucumber.features" value="classpath:com/example/features/herbs"/>
		<parameter name="cucumber.glue" value="com.example.herbs.glue"/>
		<classes>
			<class name="com.example.RunCucumberTests"/>
		</classes>
	</test>
</suite>

DataTable API Changes

Datatables can be transformed into lists, maps, lists of maps and other objects using the DataTable.asX methods. However not all asX methods would use the @DataTableType transformers that had been defined for them.

To avoid confusion all DataTable.asX methods now use a transformer. There are however a few cases where a transform should not be used (such as inside an @DataTableType annotated method). So to retain the old behaviour:

  • Replace DataTable.asList() with -> DataTable.values()
  • Replace DataTable.asLists() with -> DataTable.cells()
  • Replace DataTable.asMaps() with -> DataTable.entries()

Strict mode and non-strict mode options have been removed

Since v6 Cucumber has been executing scenarios in strict mode by default. This means that pending and undefined steps will always fail the build. This ensures that third party tools do not have to guess if pending and undefined steps should fail a test run.

To make migration graceful the --strict and --non-strict CLI arguments and cucumber.execution.strict property were left in place. These have now been removed.

Cucumber-Java8 currently under consideration for deprecation

Due to technical difficulties, the cucumber-java8 module is currently under consideration for removal. While alternatives are explored, you can already migrate to cucumber-java annotation based step definitions automatically. For now Cucumber-Java8 is removed as recommendation.