logo logo

Tidying Up Your SpecFlow Features and Scenarios

main post image

In this series of five articles, I want to help you get started with using SpecFlow in your test automation project. In this chapter, we’ll take a close look at creating more intelligent and flexible scenarios with the goal of creating expressive specifications that support communication about application behaviour and acceptance test goals and results.

Tutorial Chapters

  1. BDD, SpecFlow and The SpecFlow Ecosystem (Chapter 1)
  2. Getting Started with SpecFlow (Chapter 2)
  3. Writing More Expressive SpecFlow Steps (Chapter 3)
  4. You’re here → Tidying Up Your SpecFlow Features and Scenarios (Chapter 4)
  5. Working with SpecFlow Tables and SpecFlow.Assist (Chapter 5) – Coming next week!

In the previous article, you’ve seen a number of ways to make individual steps in SpecFlow more expressive. This helps you create steps and scenarios that are highly readable and close to the business domain language that is spoken in your organization.

In this article, we’re going to look at some other techniques that help you clean up your scenarios and feature files. As your SpecFlow project grows in size, you might find yourself repeating specific scenarios, or parts of it, as you add more feature files. The techniques demonstrated in this article will help you keep your specifications organized and well-structured without losing expressive power.

Cleaning Up Repeated Scenarios with Scenario Outline

Especially when you’re working with scenarios that involve calculations, algorithms or other types or business logic revolving around combinations of data, you will likely end up with various iterations of the same scenario, describing the same underlying logic, but with different combinations of input and output values.

This is an even more likely outcome when you’re using techniques like Example Mapping (https://cucumber.io/blog/example-mapping-introduction/) to come up with descriptive and useful examples for the behaviour that you’re trying to specify, develop and/or verify.

However, repeating the same scenario, i.e., the same business logic, over and over again, just with different data, quickly becomes tedious to read and maintain. Consider these three example scenarios for our Zippopotam.us API, where we request location data for three different combinations of country and zip code and check that the location data returned contains a specific place name:

Scenario: Country code us and zip code 90210 yields Beverly Hills
    Given the country code us and zip code 90210
    When I request the locations corresponding to these codes
    Then the response contains the place name Beverly Hills

Scenario: Country code fi and zip code 99999 yields Korvatunturi
    Given the country code fi and zip code 99999
    When I request the locations corresponding to these codes
    Then the response contains the place name Korvatunturi

Scenario: Country code ca and zip code B2A yields North Sydney South Central
    Given the country code ca and zip code B2A
    When I request the locations corresponding to these codes
    Then the response contains the place name North Sydney South Central

You can see how this quickly becomes tedious to read, as well as a burden to maintain.

To help deal with this problem, SpecFlow offers the Scenario Outline, a method to define templates for scenarios containing placeholders where the actual input and output values go, followed by Examples containing the actual values for each iteration or scenario.

Here’s what our scenarios look like after being transformed into a Scenario Outline with Examples:

Scenario Outline: Country code and zip code combinations yield the expected place names
    Given the country code <countryCode> and zip code <zipCode>
    When I request the locations corresponding to these codes
    Then the response contains the place name <expectedPlaceName>
    Examples:
        | countryCode | zipCode | expectedPlaceName          |
        | us          | 90210   | Beverly Hills              |
        | fi          | 99999   | Korvatunturi               |
        | ca          | B2A     | North Sydney South Central |

Much better! 👌 As you can see, our Scenario Outline contains placeholders for the country code, zip code and expected place name values (<countryCode>, <zipCode> and <expectedPlaceName>, respectively), which are substituted by SpecFlow with the corresponding values in the Examples table.

When we run this Scenario Outline, SpecFlow translates it into three iterations that all invoke the same logic, just with different combinations of data, which is exactly what we wanted to achieve:

Test results for a SpecFlow Scenario Outline

⚠ One warning: if you look closely at the output given by Visual Studio, you see that the examples are not run in the order in which they are specified (in this case, the underlying NUnit unit testing framework runs them in alphabetical order of the first parameter value). This should not be a problem as long as you make sure that your tests or iterations do not depend on one another, which is a good thing to practice in test automation in general.

Extracting Common Setup Steps in a Background

Another situation where you might run into step duplication and unnecessarily verbose feature files is when you have different scenarios that all require the same initial state. Consider for example these three scenarios:

Scenario: An existing country and zip code yields the correct place name
    Given the country code us and zip code 90210
    When I request the locations corresponding to these codes
    Then the response contains the place name Beverly Hills

Scenario: An existing country and zip code yields the right number of results
    Given the country code us and zip code 90210
    When I request the locations corresponding to these codes
    Then the response contains exactly 1 location

Scenario: An existing country and zip code yields the right HTTP status code
    Given the country code us and zip code 90210
    When I request the locations corresponding to these codes
    Then the response has status code 200

All three scenarios in this example share the same Given step, indicating that all three scenarios require the same initial state. While the example here is relatively brief, this can get difficult to read quickly for longer scenarios and feature files with more scenarios.

To circumvent this, SpecFlow offers the possibility to move these setup steps to a Background section, to be placed before the first scenario in your feature file. It will automatically run the steps in the Background section before each scenario in that feature file.

When we extract the common setup steps into a Background section, our feature file now looks like this:

Background: Specify country and zip code
    Given the country code us and zip code 90210

Scenario: An existing country and zip code yields the correct place name
    When I request the locations corresponding to these codes
    Then the response contains the place name Beverly Hills

Scenario: An existing country and zip code yields the right number of results
    When I request the locations corresponding to these codes
    Then the response contains exactly 1 location

Scenario: An existing country and zip code yields the right HTTP status code
    When I request the locations corresponding to these codes
    Then the response has status code 200

Running our scenarios shows us that these work in exactly the same way as before we moved the Given step into the Background section. Making this work also requires no additional changes to the step definition code.

You might have noticed that in this specific example, you could have also included the When step in the Background section. While this is technically possible in SpecFlow, it is considered good practice to only include steps that describe a required initial state in the Background. Including steps that describe the action to be undertaken (‘When’) or even assertions to be made (‘Then’) will likely result in loss of understanding with the reader as to what behaviour the scenario exactly describes.

Other Considerations

Next to the two techniques described above, there are several other guidelines that can help you make your steps and scenarios more expressive and increase their readability:

  • Use of perspective and tense. To make your scenarios come alive, use the third-person perspective and the present tense as much as possible. ‘Given Anna is a first-time user of the system’ is much easier on the eyes than ‘Given I have used the system 0 times’.
  • Only include test data that influences the outcome of the scenario. If you’re unsure as to how much detail you should go into when you’re including input variables into your scenarios, think hard about whether or not the value that a test data value takes on is important for the outcome of the scenario. Is it significant for this scenario? Then express it. Doesn’t really matter? Take care of it in the underlying step definition code. Remember, Gherkin scenarios are meant to be readable, not data-complete. Don’t be the person that specifies 137 data columns in a Gherkin scenario only because all 137 columns in a database table need a value (how I wish I made this scenario up…).

There are many other tips and tricks I could give you that help you make scenarios easier to read. Instead of listing them all here, I’d like to refer you to this blog post by Andrew Knight and this one by Thomas Sundberg for many more good tips on how to write effective Gherkin.

In the final article in this series (coming up next week!), we’re going to take a look at how you can effectively work with data tables in SpecFlow in order to work with more complex data structures as part of your Gherkin steps.

The example project used in this article can be found on GitHub: https://github.com/basdijkstra/testproject-specflow.

 

Avatar

About the author

Bas Dijkstra

Bas is an independent professional who takes pride in helping teams and organizations improve their testing efforts through smart application of tools.

Bas is also a trainer on various subjects related to testing and automation. He lives in the Netherlands with his wife and two sons and when he is not working he likes to run or to read a good book (particularly British detective novels).

Join TestProject Community

Get full access to the world's first cloud-based, open source friendly testing community. Enjoy TestProject's end-to-end test automation Platform, Forum, Blog and Docs - All for FREE.

Join Us Now  

Comments

2 2 comments
  • Five Blogs – 31 October 2019 – 5blogs October 31, 2019, 7:09 am

    […] Tidying Up Your SpecFlow Features and Scenarios Written by: Bas Dijkstra […]

  • TestProject a Virtual Community For Testers November 12, 2019, 2:57 pm

    […] has written an excellent five-part series for TestProject on getting started with SpecFlow. Rex wrote a three-part article on the Power of Using TestNG. Corina has a post on Using Java […]

Leave a Reply

Join TestProject Newsletter

Join a 20K community of readers! Always stay up-to-date with all the latest test automation trends, best practice and tips shared by leading software testing community experts across the globe!

FacebookLinkedInTwitterEmail