October 22, 2013

SpecFlow Nested Tables: A Bad Idea

I've been using SpecFlow to write behavior specifications for just under a year, and one question that comes up is whether or not nested tables are supported for creating complex or hierarchal types. Other folks have discussed this at Stack Overflow and Google Groups. Nested tables aren't currently supported, and that's probably a good thing.

The intent of the Cucumber syntax is to express business requirements in the language of the business. Nested tables don't add value from the business side because the nesting tends to make the step less readable and serves the developer more than the business. Anything that makes the steps less readable should be avoided.

Below are a couple of examples of what nested tables might look like if they were supported. The steps populate a Customer type with the simple properties FirstName and LastName, and the nested table populates ContactInformation a collection of phone numbers represented by a complex type as well.

The first example uses a double pipe delimiter to indicate the contact information. The second uses an indicator of some sort to point to the nested table. Both examples are difficult to read, and they're fairly simple compared to some of the complex types found in real systems.

# Example 1: Embedded inside the contact info cell

Given the following customer

| First Name | Last Name | Contact Information | | Gary | Smith | || Contact Type || Number || | | | | || HomePhone || 513 555-1111 || | | | | || CellPhone || 513 555-2222 || |

 

 

# Example 2: Contact info appears after the primary table specification

Given the following customer | First Name | Last Name | Contact Information | | Gary | Smith | {nested} | | Contact Type | Number | | HomePhone | 513 555-1111 | | CellPhone | 513 555-2222 |

With that said, it would still be nice to be able to build out a complex object using tables. Consider the following specification that builds out the same complex customer object.

Given the following customer
    | First Name | Last Name |
    | Gary       | Smith     |
And the following contact information
    | Customer   | Contact Type | Number       |
    | Gary Smith | HomePhone    | 513 555-1111 |
    | Gary Smith | CellPhone    | 513 555-2222 |
This is much more readable than nested tables.  Even with more data it remains easy to follow.
Given the following customer
    | First Name | Last Name |
    | Gary       | Smith     |
    | Kim        | Green     |
And the following contact information
    | Customer   | Contact Type | Number       |
    | Gary Smith | HomePhone    | 513 555-1111 |
    | Gary Smith | CellPhone    | 513 555-2222 |
    | Kim Green  | CellPhone    | 513 555-3333 |
    | Kim Green  | WorkPhone    | 513 555-4444 |
And the following addresses
    | Customer   | Address Type | Street          | City       | State |
    | Gary Smith | Home         | 111 Main Street | Cincinnati | OH    |
    | Gary Smith | Work         | 111 Poplar Road | Cincinnati | OH    |
    | Kim Green  | Home         | 222 Main Street | Cincinnati | OH    |
    | Kim Green  | Work         | 333 Poplar Road | Cincinnati | OH    |

Now imagine what this would look like with nested tables. No matter how elegant the proposed syntax, it would be very difficult for non-technical people to follow.

© Joe Buschmann 2020