Given-When-Then examples work nicely with structured data, particularly if it can fit well into tables. Things become tricky with data that has more than two levels of hierarchy. For example, a scenario might involve several users, each with several addresses and accounts, and transactions within each account. This does not fit neatly into a single table. The challenge for this week is describing those kinds of hierarchies in Gherkin.
Below are a few common options for you to choose, based on what I’ve seen in the wild. This challenge is probably more open-ended than the previous ones, since there are many other ways to solve the same problem. If you know of a better way, please post your solution somewhere and send us the link (using the voting form linked at the end of this post).
Option 1: chain together individual entities
The first way of specifying hierarchical data is to start at a higher level for the context (in this case “user”), and use it to provide context for the following statements, implicitly specifying the hierarchy:
Given user Leto With the following addresses | type | street address | city | | home | Central Plaza 1 | Caladan | | office | Grand Palace | Arrakeen | And the following account | type | currency | balance | status | | current | USD | 100 | active | And the following transactions in account | date | amount | description | | 2 January | 2000 | flight ticket | | 3 January | 1500 | desert suit | And the following account | type | currency | balance | status | | credit | USD | -400 | active | And the following transactions in the account | date | amount | description | | 1 January | 5000 | spice | | 2 January | 7500 | spice | | 4 January | 5500 | spice | Given user Vladimir With the following addresses | type | street address | city | | office | Shield Wall Street | Carthag | ...
Option 2: relational table normalisation
Alternatively, instead of chaining entities to provide context, we could introduce identifiers and just represent the hierarchy as flat tables, similar to a relational database.
Given the following users: | userid | name | | UID_1 | Leto | | UID_2 | Vladimir | And the following addresses: | userid | type | street address | city | | UID-1 | home | Central Plaza 1 | Caladan | | UID-1 | office | Grand Palace | Arrakeen | | UID-2 | office | Shield Wall Street | Carthag | | UID-2 | home | Star Jewel 2 | Giedi Prime | And the following accounts: | accountid | userid | type | currency | balance | status | | AID_1 | UID-1 | current | USD | 100 | active | | AID_2 | UID-1 | credit | USD | -400 | active | | AID_3 | UID-2 | credit | RUB | -400000 | active | And the following transactions: | accountid | date | amount | description | | AID_1 | 2 January | 2000 | flight ticket | | AID_1 | 3 January | 1500 | desert suit | | AID_2 | 1 January | 5000 | spice | | AID_2 | 2 January | 7500 | spice | | AID_2 | 4 January | 5500 | spice | ...
Option 3: embed hierarchy as text
Gherkin does not have a good way to embed tables into tables, but it does support free-form text enclosed in three quotes. We could use a hierarchical text format (such as YAML, JSON, or even just simple indentation) and then parse the string into a hierarchy of objects in the step implementation. This would allow us to specify the entire user hierarchy in a visual way, at the expense of more complex parsing.
Given the user """ name: Leto addresses: - type: home street: Central Plaza 1 city: Caladan - type: office street: Grand Palance city: Arakeen accounts: - type: current currency: USD balance: 100 status: active transactions: - date: 2 January amount: 2000 description: flight ticket - date: 3 January amount: 1500 description: desert suit - type: credit currency: USD balance: -100 status: active transactions: - date: 2 January amount: 75000 description: spice - date: 3 January amount: 5500 description: spice """ And the user """ name: Vladimir addresses: - type: home street: Star Jewel 2 city: Giedy Prime """ ...
Option 4: use data in external files
Instead of embedding all that hierarchical data, we could also move it to an external file, and provide just the file name to the automation step:
Given the user Leto with data from users/leto_a.txt And the user Vladimir with data from users/vladimir_h.txt
Participate in the challenge
Choose one of the options you like the best, or propose your own solution. You can post short answers directly in the form below. For longer explanations, perhaps post your suggestion somewhere and send us the link.
To participate, send your answers by Monday 22nd February. We will post the results on Tuesday 23rd February.
PS: … and don’t forget to share the challenge with your friends and team members by clicking on one of the social icons below 👇