SpecFlow — a few tips-n-tricks Part 2

Jay Barden
Capgemini Microsoft Blog
4 min readFeb 12, 2020

Welcome to the second part of the SpecFlowa few tips-n-tricks article. In the first part, we saw how to share steps between files and projects within our solution, but we can do more. I won’t say most tests require data as that will vary depending on the project, but I will say a lot of tests will require data. In this continuation, I will endeavour to share some tips-n-tricks on how to share data between your steps and how to make working with data — single values or tables — much simpler and in a strongly-typed way.

Step Parameters and Data Tables

Whether the data is supplied to the step from a single parameter inline in the method or from a Scenario Outline > Examples table of an inline Data Table, data will often play a significant part in the step definition. Below are some approaches that can be used to simplify working with data.

Sharing data between steps

Sharing data between one or more steps for a scenario can be extremely common. Below are the main options available within SpecFlow:

  1. Private field. Whilst a private field can be used within the class, that won’t work if the steps are in different classes (or assemblies).
  2. ScenarioContext.Current is an option as it supplies a string-based dictionary that you can add to / read from.
  3. Injection of the ScenarioContext via the frameworks DI (dependency inversion). This is basically the same as option 2, but is another way to obtain an instance of the ScenarioContext.
  4. Context Injection is the SpecFlow recommended solution:

This option is recommended as it injects a strongly-typed class (or classes) rather than a string-based dictionary 😃 SpecFlow handles the injection automatically and it is available across classes and assemblies.

Step Argument Conversion Precedence

This is possibly my favourite feature within the SpecFlow framework. 😃 There are 3 types of conversion:

  1. No conversion — e.g. a string is used in the GWT (Given…When…Then…) and a string is expected by the target method.
  2. Custom conversion — see below.
  3. Standard conversion — e.g. any conversion that SpecFlow supplies out of the box. (In reality, SpecFlow uses the Convert.ChangeType method from the .Net Framework...). The conversion I particularly like here is the automatic conversion to an enum.

Custom Conversions

Custom conversions allow us to take control of the conversion process if we need to. For example, rather than:

The step definition can become:

And here is the magic:

There are other ways to do this, but this is pretty neat!
Please note: this does not work if the data is coming from a data table.

Converting Data Tables to Strongly-typed Collections

Working with Table data in code is ugly:

(A foreach loop could be used to clean the above example, but the resulting code would still obscure the intent of the test step.)

Using the custom conversions, the above code can become:

The above magic requires an additional NuGet package: SpecFlow.Assist.Dynamic — there are several other methods available.

Remember the magic earlier? The above can be encapsulated into a custom conversion (as shown for DateTime) and allows for an even simpler step definition:

Too many classes / not worth creating a class just for one or two scenario tables?:

(I would normally use varrather than IEnumerable<dynamic>but I’ve left here for added clarity.)

For both extensions (CreateSet<T> and CreateDynamicSet), the Column names in the table are used to match the properties in the class / create the dynamic properties in the dynamic object — remember, run-time validation of the dynamic properties happens, not compile-type checking of properties so my advice is to only use dynamic sparingly to prevent surprises. I’ve included here as it will work, I just prefer to create suitable classes nearly all the time.

The above example, can become (as the nice people who created SpecFlow.Assist.Dynamic have added the transform already):

As we have seen, there are a lot of different ways to share data between our steps and to make working with our data easier.

Happy Testing!

Interested in working with like-minded people?

Join the Capgemini Microsoft team, open roles here.

--

--