Jeroen
Jeroen

Reputation: 1755

c# SpecFlow BeforeScenario hooks

I'm programming several Scenario's in one Feature file. I'm using one big Steps file to bind the Scenario steps to code.

For example my Feature file looks like this:

Feature: Feature1
    Description of feature1

@TagA @TagB
Scenario: Scenario1
    Given Some form
    When I press the submit button
    Then I end up at a page

@TagA
Scenario: Scenario2
    Given Some form
    When I press cancel
    Then I should end up at a different page

And my Step file looks like this:

using System;
using TechTalk.SpecFlow;

namespace UpdateServer.AcceptanceTests.StepFiles
{
    [Binding]
    [Scope(Feature = "Feature1")]
    public class Feature1Steps : SeleniumTestsBaseClass
    {
        [BeforeScenario("TagA")]
        public void BeforeScenarioTagA()
        {
            // prepare some stuff
        }

        [BeforeScenario("TagB")]
        public void BeforeScenarioTagB()
        {
            // prepare some other stuff
        }

        [Given(@"Some form")]
        public void GivenSomeForm()
        {
            // navigate to form
        }

        [When(@"I press the submit button")]
        public void WhenIPressTheSubmitButton()
        {
            // press submit button
        }

        [When(@"I press cancel")]
        public void WhenIPressCancel()
        {
            // press cancel button
        }

        [Then(@"I end up at a page")]
        public void ThenIEndUpAtAPage()
        {
            // check url
        }

        [Then(@"I should end up at a different page")]
        public void ThenIShouldEndUpAtADifferentPage()
        {
            // check url
        }
    }
}

Notice that my step files inherits from a base class which has some general given,when,then bindings and one AfterScenario which closes the webdriver.

Now when I run Scenario2 it will execute the BeforeScenario of TagB as well. Ofcourse I don't want this behaviour, why does SpecFlow still execute the TagB code in this context? And how can I stop it from doing that?

Edit

The SeleniumTestsBaseClass is used to initialize a Selenium WebDriver in the constructor of this base class. This is the reason why the Scope has been added to the steps class because all my step classes inherit from the base class. Removing this Scope attribute results in a WebDriver to be opened for every step file there is, even when only one test is being run.

Follow up question: What's the best place to initialize my WebDriver without risking it being opened more times than necessary?

Upvotes: 1

Views: 4010

Answers (1)

Matt Hogan-Jones
Matt Hogan-Jones

Reputation: 3113

I believe the reason the BeforeScenario steps are being applied to all your scenarios regardless of tags is because of your scoping the Feature1Steps class to the Feature1 feature.

I did some testing - if you remove all of the tags from your scenarios, both BeforeScenario steps still get run. Same if you add a new scenario with no tags to your existing feature.

I think SpecFlow is seeing you specifying the scope of your steps class and this is a higher precedence than your tag scoping - so it will run the BeforeScenario steps for any scenario in Feature1.

Removing the [Scope(Feature = "Feature1")] attribute from your Feature1Steps class correctly applies the specific BeforeScenario step based on your chosen tags, but without knowing why you've chosen to scope all your bindings to a specific feature I can't comment on whether removing this scope is a good idea.

Although it is considered an anti-pattern to couple step definitions to features and scenarios - read more on the Cucumber wiki.

Upvotes: 2

Related Questions