I've written a number of posts since this one was published that cover advanced SpecFlow topics like composable steps, tags done right, managing state, useful regex, etc. For a list of all my SpecFlow writing, you can click on the SpecFlow tag or go here: http://joebuschmann.com/tag/specflow. SpecFlow is a fantastic tool that's changed the way I develop software, and I hope it does the same for you. Happy testing!
Late last year a co-worker Jay Brummels introduced our development group to SpecFlow a .NET tool that enables behavior specifications from a domain expert or product owner to be bound to runnable test code. It has been a huge success, and we're quickly building up a suite of system tests and unit tests fronted by SpecFlow.
Although we're relatively new to SpecFlow, my group has identified some patterns or best practices to follow when building out tests.
Use Extension Methods to Manipulate ScenarioContext.Current
Using ScenarioContext to store state is no longer recommended. Instead use dependency injection to share state between steps and bindings. For more information, see my post on strategies for managing state.
ScenarioContext.Current is a singleton that provides contextual information about the test and executing scenario block as well as a dictionary data structure for storing test data between scenario blocks. Below is an example of retrieving an object, manipulating it, and stashing it back in ScenarioContext dictionary.
Using the dictionary directly from step code has some disadvantages. First access to the data requires passing a string key which is not discoverable via Intellisense. Second creating an object may require multiple dictionary items to build it out. Having that logic in multiple places is prone to error.
To solve these issues, extension methods can be used to store and retrieve test data.
And to take things one step further, the creation of a complex object using multiple entries in the dictionary can be hidden behind an extension method.
Bind Multiple Specification AttributesAfter writing out a step specification, step definitions need to be generated and filled in with the implementation code. Whenever I notice the same step definition being used from different scenario blocks, I like to consolidate them into one method and add multiple step definition attributes. Also, I like to rename the method to something more concise. By default SpecFlow generates method names that match the step specification text, and they tend to be long and wordy.
Use Hooks to Execute Setup or Teardown CodeAs with any other testing framework, SpecFlow provides a way of executing setup or teardown code for features, scenarios, steps, and test runs via hook classes. Hooks are associated to tests using tags which are keywords preceded by an @ symbol.
At work my development group has created a series of system tests for an ordering system. Each test places an actual order in an integrated testing environment. After a test run, dozens of orders remain in the system taking up valuable space and resources. To solve this problem, a hook runs after each ordering scenario to cancel the order and remove it from the system.
Tests scenarios that create orders can use the @CancelOrder tag to run the hook after the scenario completes.