|  | 
|  | 1 | +Cucumber Java8 | 
|  | 2 | +============== | 
|  | 3 | + | 
|  | 4 | +Provides lambda based step definitions. To use add the `cucumber-java8` dependency to your pom.xml: | 
|  | 5 | + | 
|  | 6 | +```xml | 
|  | 7 | +<dependencies> | 
|  | 8 | +  [...] | 
|  | 9 | +    <dependency> | 
|  | 10 | +        <groupId>io.cucumber</groupId> | 
|  | 11 | +        <artifactId>cucumber-java8</artifactId> | 
|  | 12 | +        <version>${cucumber.version}</version> | 
|  | 13 | +        <scope>test</scope> | 
|  | 14 | +    </dependency> | 
|  | 15 | +  [...] | 
|  | 16 | +</dependencies> | 
|  | 17 | +``` | 
|  | 18 | + | 
|  | 19 | +## Step Definitions | 
|  | 20 | + | 
|  | 21 | +Declare a step definition calling a method in the constructor of the glue class. | 
|  | 22 | +For localized methods import the interface from `io.cucumber.java8.<ISO2 Language Code>` | 
|  | 23 | + | 
|  | 24 | +Data tables and Docstrings from Gherkin can be accessed by using a `DataTable` | 
|  | 25 | +or `DocString` object as the last parameter. | 
|  | 26 | + | 
|  | 27 | +```java | 
|  | 28 | +package com.example.app; | 
|  | 29 | + | 
|  | 30 | +import io.cucumber.java8.En; | 
|  | 31 | +import io.cucumber.datatable.DataTable; | 
|  | 32 | +import io.cucumber.docstring.DocString; | 
|  | 33 | + | 
|  | 34 | +import static org.junit.jupiter.api.Assertions.assertEquals; | 
|  | 35 | + | 
|  | 36 | +public class StepDefinitions implements En { | 
|  | 37 | + | 
|  | 38 | +    private RpnCalculator calc; | 
|  | 39 | + | 
|  | 40 | +    public RpnCalculatorSteps() { | 
|  | 41 | +        Given("a calculator I just turned on", () -> { | 
|  | 42 | +            calc = new RpnCalculator(); | 
|  | 43 | +        }); | 
|  | 44 | + | 
|  | 45 | +        When("I add {int} and {int}", (Integer arg1, Integer arg2) -> { | 
|  | 46 | +            calc.push(arg1); | 
|  | 47 | +            calc.push(arg2); | 
|  | 48 | +            calc.push("+"); | 
|  | 49 | +        }); | 
|  | 50 | + | 
|  | 51 | +        Then("the result is {double}", (Double expected) -> assertEquals(expected, calc.value())); | 
|  | 52 | + | 
|  | 53 | +        Given("the previous entries:", (DataTable dataTable) -> { | 
|  | 54 | +            List<Entry> entries = dataTable.asList(Entry.class); | 
|  | 55 | +            ... | 
|  | 56 | +        }); | 
|  | 57 | + | 
|  | 58 | +        Then("the calculation log displays:", (DocString docString) -> { | 
|  | 59 | +            ... | 
|  | 60 | +        }); | 
|  | 61 | +    } | 
|  | 62 | +} | 
|  | 63 | +``` | 
|  | 64 | + | 
|  | 65 | +## Hooks | 
|  | 66 | + | 
|  | 67 | +Declare hooks that will be executed before/after each scenario/step by calling a | 
|  | 68 | +method in the constructor. The method may declare an argument of type `io.cucumber.java8.Scenario`. | 
|  | 69 | + | 
|  | 70 | + * `Before`  | 
|  | 71 | + * `After` | 
|  | 72 | + * `BeforeStep` | 
|  | 73 | + * `AfterStep` | 
|  | 74 | +  | 
|  | 75 | +## Transformers  | 
|  | 76 | + | 
|  | 77 | +### Parameter Type | 
|  | 78 | + | 
|  | 79 | +Step definition parameter types can be declared by using `ParameterType`. | 
|  | 80 | + | 
|  | 81 | +```java | 
|  | 82 | +package com.example.app; | 
|  | 83 | + | 
|  | 84 | +import io.cucumber.java8.En; | 
|  | 85 | + | 
|  | 86 | +import static org.junit.jupiter.api.Assertions.assertEquals; | 
|  | 87 | + | 
|  | 88 | +public class StepDefinitions implements En { | 
|  | 89 | + | 
|  | 90 | +    public StepDefinitions() { | 
|  | 91 | +        ParameterType("amount", "(\\d+\\.\\d+)\\s([a-zA-Z]+)", (String[] values) -> | 
|  | 92 | +            new Amount(new BigDecimal(values[0]), Currency.getInstance(values[1]))); | 
|  | 93 | +    } | 
|  | 94 | +} | 
|  | 95 | +```  | 
|  | 96 | + | 
|  | 97 | +### Data Table Type | 
|  | 98 | + | 
|  | 99 | +Data table types can be declared by calling `DataTableType` in the constructor. | 
|  | 100 | +Depending on the lambda type this will be either a:  | 
|  | 101 | + * `String` -> `io.cucumber.datatable.TableCellTranformer` | 
|  | 102 | + * `Map<String,String>` -> `io.cucumber.datatable.TableEntry` | 
|  | 103 | + * `List<String>` -> `io.cucumber.datatable.TableRow` | 
|  | 104 | + * `DataTable` -> `io.cucumber.datatable.TableTransformer` | 
|  | 105 | + | 
|  | 106 | +```java | 
|  | 107 | +package com.example.app; | 
|  | 108 | + | 
|  | 109 | +import io.cucumber.java8.En; | 
|  | 110 | + | 
|  | 111 | +import java.util.Map; | 
|  | 112 | + | 
|  | 113 | +import static org.junit.jupiter.api.Assertions.assertEquals; | 
|  | 114 | + | 
|  | 115 | +public class StepDefinitions implements En { | 
|  | 116 | + | 
|  | 117 | +    public StepDefinitions() { | 
|  | 118 | +        DataTableType((Map<String, String> row) -> new Grocery( | 
|  | 119 | +            row.get("name"), | 
|  | 120 | +            Price.fromString(row.get("price")) | 
|  | 121 | +        )); | 
|  | 122 | +    } | 
|  | 123 | +} | 
|  | 124 | +```  | 
|  | 125 | + | 
|  | 126 | +### Default Transformers | 
|  | 127 | + | 
|  | 128 | +Default transformers allow you to specific a transformer that will be used when | 
|  | 129 | +there is no transform defined. This can be combined with an object mapper like | 
|  | 130 | +Jackson to quickly transform well known string representations to Java objects. | 
|  | 131 | + | 
|  | 132 | + * `DefaultParameterTransformer` | 
|  | 133 | + * `DefaultDataTableEntryTransformer` | 
|  | 134 | + * `DefaultDataTableCellTransformer` | 
|  | 135 | +  | 
|  | 136 | +For a full list of transformations that can be achieved with data table types | 
|  | 137 | +see [cucumber/datatable](https://github.com/cucumber/cucumber/tree/master/datatable) | 
|  | 138 | +  | 
|  | 139 | +```java | 
|  | 140 | +package com.example.app; | 
|  | 141 | + | 
|  | 142 | +import com.fasterxml.jackson.databind.ObjectMapper; | 
|  | 143 | + | 
|  | 144 | +import io.cucumber.java8.En; | 
|  | 145 | + | 
|  | 146 | +public class StepDefinitions implements En { | 
|  | 147 | + | 
|  | 148 | +    public StepDefinitions() { | 
|  | 149 | +        final ObjectMapper objectMapper = new ObjectMapper(); | 
|  | 150 | + | 
|  | 151 | +        DefaultParameterTransformer((fromValue, toValueType) -> | 
|  | 152 | +            objectMapper.convertValue(fromValue, objectMapper.constructType(toValueType)) | 
|  | 153 | +        ); | 
|  | 154 | +    } | 
|  | 155 | +} | 
|  | 156 | +```  | 
|  | 157 | + | 
|  | 158 | +### Empty Cells | 
|  | 159 | + | 
|  | 160 | +Data tables in Gherkin can not represent null or the empty string unambiguously. | 
|  | 161 | +Cucumber will interpret empty cells as `null`. | 
|  | 162 | + | 
|  | 163 | +Empty string be represented using a replacement. For example `[empty]`. | 
|  | 164 | +The replacement can be configured providing the `replaceWithEmptyString` | 
|  | 165 | +argument of `DataTableType`, `DefaultDataTableCellTransformer` and  | 
|  | 166 | +`DefaultDataTableEntryTransformer`. By default no replacement is configured.  | 
|  | 167 | + | 
|  | 168 | +```gherkin | 
|  | 169 | +Given some authors | 
|  | 170 | +   | name            | first publication | | 
|  | 171 | +   | Aspiring Author |                   | | 
|  | 172 | +   | Ancient Author  | [blank]           | | 
|  | 173 | +``` | 
|  | 174 | + | 
|  | 175 | +```java | 
|  | 176 | +package com.example.app; | 
|  | 177 | + | 
|  | 178 | +import io.cucumber.datatable.DataTable; | 
|  | 179 | + | 
|  | 180 | +import io.cucumber.java8.En; | 
|  | 181 | + | 
|  | 182 | +import java.util.List; | 
|  | 183 | +import java.util.Map; | 
|  | 184 | +import java.util.Optional; | 
|  | 185 | + | 
|  | 186 | +import static org.junit.jupiter.api.Assertions.assertEquals; | 
|  | 187 | +import static org.junit.jupiter.api.Assertions.assertNotSame; | 
|  | 188 | +import static org.junit.jupiter.api.Assertions.assertSame; | 
|  | 189 | +import static org.junit.jupiter.api.Assertions.assertTrue; | 
|  | 190 | + | 
|  | 191 | +public class StepDefinitions implements En { | 
|  | 192 | +     | 
|  | 193 | +    public StepDefinitions() { | 
|  | 194 | +        DataTableType("[blank]", (Map<String, String> entry) -> new Author( | 
|  | 195 | +            entry.get("name"), | 
|  | 196 | +            entry.get("first publication") | 
|  | 197 | +        )); | 
|  | 198 | +     | 
|  | 199 | +        Given("some authors",  (DataTable authorsTable) -> { | 
|  | 200 | +            List<Author> authors = authorsTable.asList(Author.class); | 
|  | 201 | +          // authors = [Author(name="Aspiring Author", firstPublication=null), Author(name="Ancient Author", firstPublication=)] | 
|  | 202 | + | 
|  | 203 | +        }); | 
|  | 204 | +    } | 
|  | 205 | +} | 
|  | 206 | +``` | 
|  | 207 | + | 
|  | 208 | +# Transposing Tables | 
|  | 209 | + | 
|  | 210 | +A data table can be transposed by calling `.transpose()`. This means the keys | 
|  | 211 | +will be in the first column rather then the first row. | 
|  | 212 | + | 
|  | 213 | +```gherkin | 
|  | 214 | + Given the user is | 
|  | 215 | +    | firstname	    | Roberto	| | 
|  | 216 | +    | lastname	    | Lo Giacco | | 
|  | 217 | +    | nationality	| Italian	| | 
|  | 218 | + ``` | 
|  | 219 | + | 
|  | 220 | +And a data table type to create a User | 
|  | 221 | + | 
|  | 222 | +```java  | 
|  | 223 | +package com.example.app; | 
|  | 224 | + | 
|  | 225 | +import io.cucumber.datatable.DataTable; | 
|  | 226 | + | 
|  | 227 | +import io.cucumber.java8.En; | 
|  | 228 | + | 
|  | 229 | +import java.util.List; | 
|  | 230 | +import java.util.Map; | 
|  | 231 | +import java.util.Optional; | 
|  | 232 | + | 
|  | 233 | +import static org.junit.jupiter.api.Assertions.assertEquals; | 
|  | 234 | +import static org.junit.jupiter.api.Assertions.assertNotSame; | 
|  | 235 | +import static org.junit.jupiter.api.Assertions.assertSame; | 
|  | 236 | +import static org.junit.jupiter.api.Assertions.assertTrue; | 
|  | 237 | + | 
|  | 238 | +public class StepDefinitions implements En { | 
|  | 239 | +     | 
|  | 240 | +    public StepDefinitions() { | 
|  | 241 | +        DataTableType((Map<String, String> entry) -> new User( | 
|  | 242 | +            entry.get("firstname"), | 
|  | 243 | +            entry.get("lastname") | 
|  | 244 | +            entry.get("nationality") | 
|  | 245 | +        )); | 
|  | 246 | +     | 
|  | 247 | +        Given("the user is",  (DataTable authorsTable) -> { | 
|  | 248 | +            User user = authorsTable.transpose().asList(User.class); | 
|  | 249 | +            // user  = User(firstname="Roberto", lastname="Lo Giacco", nationality="Italian") | 
|  | 250 | +        }); | 
|  | 251 | +    } | 
|  | 252 | +} | 
|  | 253 | +``` | 
0 commit comments