/
externaldata.md
239 lines (152 loc) · 10.4 KB
/
externaldata.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# External Data Plugin
You can easily apply standardized test cases across a wide range of features to significantly reduce
redundant data for large test suites. By reusing execution flows, you can also speed up exploratory and approval testing
for ranges of examples. Reqnroll makes all of this possible by introducing support for loading external data into
scenarios easily.
The [Reqnroll ExternalData plugin](https://www.nuget.org/packages/Reqnroll.ExternalData/) lets teams separate test data from test scenarios, and reuse examples across a large set of scenarios. This is particularly helpful when a common set of examples needs to be consistently verified in different scenarios.
Simply download the [NuGet package](https://www.nuget.org/packages/Reqnroll.ExternalData/) and add it to your reqnroll projects to use it.
## Supported Data Sources
- CSV files (format 'CSV', extension .csv)
```{note}
Standard RFC 4180 CSV format is supported with a header line (plugin uses [CsvHelper](https://github.com/JoshClose/CsvHelper) to parse the files).
```
- Excel files (format Excel, extensions .xlsx, .xls, .xlsb)
```{note}
Both XLSX and XLS is supported (plugin uses [ExcelDataReader](https://github.com/ExcelDataReader/ExcelDataReader) to parse the files).
```
- JSON files (format 'JSON', extension .json)
```{note}
Object arrays and nested object arrays are supported (plugin uses [JObject.Parse](https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Linq/JObject.cs) to parse the files).
```
## Tags
The following tags can be used to specify the external source:
- `@DataSource:path-to-file` - This tag is the main tag that you can add to a scenario or a scenario outline to specify the data source you wish to use.
```{caution}
The path is a relative path to the folder of the **feature files**.
```
- `@DisableDataSource` - The `@DataSource` tag can be added to the feature node, turning all scenarios in the file to scenario outlines. This method is useful when the entire feature file uses the same data source. Use the `@DisableDataSource` If you want a select few scenarios in the feature file to **not** use the data source tagged at feature node level.
- `@DataFormat:format` - This tag only needs to be used if the format cannot be identified from the file extension.
- `@DataSet:data-set-name` - This tag is applicable to *Excel and Json files only*. For Excel it is used to select the worksheet of the Excel file you wish to use. By **default**, the first worksheet in an Excel file is targeted. For Json it is used to select the object array you wish to use. By **default**, the first object array in a Json file is targeted.
- `@DataField:name-in-feature-file=name-in-source-file` - This tag can be used to "rename" columns of the external data source.
General notes on tags:
- Tags can be added on feature, scenario, scenario outline or scenario outline examples.
- Tags can inherit from the feature node, but you can override them with another tag or disable them by using the `@DisableDataSource` tag on the scenario level.
- As tags cannot contain spaces, generally the underscore (_) character can be used to represent a space. It is currently not supported to access a file that contains spaces in the file name or in the relative path.
## Examples
### CSV files
The below examples all use the same ***products.csv*** file. The file contains three products and their corresponding prices:
![product csv](/_static/images/productscsv.png)
- This scenario will be treated as a scenario outline with the products from the CSV file replacing the **<product<product>>** parameter in the given statement:
````Gherkin
@DataSource:products.csv
Scenario: Valid product prices are calculated
Given the customer has put 1 piece of <product> in the basket
When the basket price is calculated
Then the basket price should be greater than zero
````
- This scenario will be treated as a scenario outline similar to the above example but uses both **<product<product>>** and **<price<price>>** from the CSV file:
````Gherkin
@DataSource:products.csv
Scenario: The basket price is calculated correctly
Given the price of <product> is €<price>
And the customer has put 1 pcs of <product> to the basket
When the basket price is calculated
Then the basket price should be €<price>
````
- This scenario shows how you can extend the product list using the example table with the ones from the CSV file. A total of 4 products will be added here, 3 from the CSV file plus "Cheesecake" from the example table:
````Gherkin
@DataSource:products.csv
Scenario Outline: Valid product prices are calculated (Outline)
Given the customer has put 1 pcs of <product> to the basket
When the basket price is calculated
Then the basket price should be greater than zero
Examples:
| product |
| Cheesecake |
````
You may also add the `@DataSource` above the example table if you wish to:
````Gherkin
Scenario Outline: Valid product prices are calculated (Outline, example annotation)
Given the customer has put 1 pcs of <product> to the basket
When the basket price is calculated
Then the basket price should be greater than zero
@DataSource:products.csv
Examples:
| product |
| Cheesecake |
````
- In this scenario the parameters names do not match the column names in the CSV file but we can address that by using the `@DataField:product-name=product` and `@DataField:price-in-EUR=price` tags:
````Gherkin
@DataSource:products.csv @DataField:product-name=product @DataField:price-in-EUR=price
Scenario: The basket price is calculated correctly (renamed fields)
Given the price of <product-name> is €<price-in-EUR>
And the customer has put 1 piece of <product-name> in the basket
When the basket price is calculated
Then the basket price should be €<price-in-EUR>
````
- This scenario is similar to the above scenario with the renaming of the parameters, but the difference is the use of space in the parameter name. Spaces are **not** supported and must be replaced with underscore (_):
````Gherkin
@DataSource:products.csv @DataField:product_name=product @DataField:price-in-EUR=price
Scenario: The basket price is calculated correctly
Given the customer has put 1 piece of <product name> in the basket
When the basket price is calculated
Then the basket price should be greater than zero
Examples:
| product name |
| Cheesecake |
````
### Excel files
You can use Excel files the same way as you do with CSV files with some minor differences:
- Only simple worksheets are supported, where the **header is in the first row** and the data comes right below that. Excel files that contain tables, graphics, etc. are not supported.
- Excel files with multiple worksheets are supported, you can use the `@DataSet:sheet-name` to select the worksheets you wish to target. The plugin uses the **first** worksheet by **default**.
- Use underscores in the `@DataSet` tag instead of spaces if the worksheet name contains spaces.
The below example shows an Excel file with multiple worksheets and we wish to target the last worksheet labelled *"other products"*. We do this by using the `@DataSet:other_products` tag. Note the use of (_) instead of space:
![product excel](/_static/images/excel.png)
````Gherkin
@DataSource:products.xlsx @DataSet:other_products
Scenario: The basket price is calculated correctly for other products
Given the price of <product> is €<price>
And the customer has put 1 piece of <product> in the basket
When the basket price is calculated
Then the basket price should be €<price>
````
## Language Settings
The decimal and date values read from an Excel file will be exported using the language of the feature file (specified using the `#language` setting in the feature file or in the Reqnroll configuration file). This setting affects for example the decimal operator as in some countries comma (,) is used as decimal separator instead of dot (.). To specify not only the language but also the country use the `#language: language-country` tag, e.g. *#language: de-AT* for *Deutsch-Austria*.
Example: Hungarian uses comma (,) as decimal separator instead of dot (.), so Reqnroll will expect the prices in format 1,23:
This sample shows that the language settings are applied for the data that is being
read by the external data plugin.
````Gherkin
#language: hu-HU
Jellemző: External Data from Excel file (Hungarian)
@DataSource:products.xlsx
Forgatókönyv: The basket price is calculated correctly
Amennyiben the price of <product> is €<price>
És the customer has put 1 pcs of <product> to the basket
Amikor the basket price is calculated
Akkor the basket price should be €<price>
````
### Json files
You can use Json files the same way as you do with Excel files with some minor differences:
- Only Object arrays and nested Object are supported. Arrays of simple types, empty arrays, etc. are not supported.
- Json files with multiple object arrays are supported, you can use the `@DataSet:array-property-name` to select the object array you wish to target. The plugin uses the **first** object array by **default**. Nested object arrays can be specified by appending property names using a '.'.
- Use underscores in the `@DataSet` tag instead of spaces if the array property name name contains spaces.
The below example shows a Json file with object arrays and we wish to target the last array labelled *"other products"*. We do this by using the `@DataSet:other_products` tag. Note the use of (_) instead of space:
![product json](/_static/images/jsonDatasetWithSpace.png)
````Gherkin
@DataSource:products.json @DataSet:other_products
Scenario: The basket price is calculated correctly for other products
Given the price of <product> is €<price>
And the customer has put 1 pcs of <product> to the basket
When the basket price is calculated
Then the basket price should be €<price>
````
The below example shows a Json file with nested object arrays and we wish to target the inner array labelled *"varieties"*. We do this by using the `@DataSet:products.varieties` tag. Note the use of . to append nested property names:
![product.varieties json](/_static/images/jsonDatasetWithNestedObjectArrays.png)
````Gherkin
@DataSource:products-nested-dataset.json @DataSet:products.varieties
Scenario: The basket price is calculated correctly for products.varieties in nested products json
Given the price of <product> is €<price>
And the customer has put 1 pcs of <product> to the basket
When the basket price is calculated
Then the basket price should be €<price>
````