0
votes

I have specflow parallel feature execution working for my test suite, but at the moment, it will open up a brand new browser for every single scenario in that feature. Is there any way to make it so it doesn't do this? Because having to restart the browser for every single scenario will take up a lot of extra time when we have hundreds of scenarios. All I want is for the browser to stay open, so I can navigate to wherever the next scenario needs to go, but right now it just starts up a brand new driver every time.

This is the hook class:

    [Binding]
    public class Hook
    {

        private readonly IObjectContainer _container;
        private IWebDriver _driver;
        public Hook(IObjectContainer container)
        {
            _container = container;
        }

        [BeforeScenario]
        private void SetupTest()
        {
            if (_driver == null)
            {
                _driver = new ChromeDriver();
            }
            _container.RegisterInstanceAs<IWebDriver>(_driver);
        }

 ....
    }

And this is my step class:

[Binding]
public class TestSteps
{

    private IWebDriver _driver;

    public TestSteps(IWebDriver driver)
    {
        _driver = driver;
    }

....
}

Here is an example feature file:

Feature: Test1

Background:
    Given User is at login page

Scenario: HelpPage
    Given page is loaded
    When user clicks on help
    Then user should be taken to help page

Scenario: AboutPage
    Given page is loaded
    When user clicks on about
    Then user should be taken to about page


Feature: Test2

Background:
    Given User is at login page

Scenario: Welcome
    When the page is loaded
    Then should see welcome message

So basically right now test1 and test2 can run in parallel, but for test1, after the help page scenario is done, it will start up a new webdriver and then do the about page scenario, what I want it to do is after the help page scenario is done, have it navigate to the login page (background) in that same browser/webdriver, and will then go on to test the about page scenario, all without having start up a new browser and webdriver.

Is there any way to change this so I am able to continue onto the next scenario in my feature file without it starting a brand new driver? As you can see I have tried checking if driver is null, but this doesn't work as it always seems to be null when it moves onto the next scenario in the feature file.

EDIT: I have also tried setting the driver through the feature context key in AfterScenario, and setting it in beforescenario, this lets one scenario run after the other, but when I run two features in parallel, I will now get a

"System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation." error.

Possibly because both features are using steps from the same step file?

1
This is going to be very difficult, if not impossible. You are fighting how SpecFlow parallel tests were meant to be used.Greg Burghardt

1 Answers

0
votes

This because you are using IObjectContainer.

The life-time of the objects is limited to a scenario's execution.

Refer: https://github.com/techtalk/SpecFlow/wiki/Context-Injection

After the scenario execution completes specflow will dispose the objects.

Solution

You can create a class something like DriverContext and create a method to initialize your driver then call this method in [BeforeScenario]

[Binding]
    public class Hook
    {

        private DriverContext _driverContext;            
        public Hook(DriverContext driverContext)
        {
            _driverContext= driverContext;
        }

        [BeforeScenario]
        private void SetupTest()
        {
            if (_driverContext.Driver == null)
            {
                _driverContext.StartDriver();
            }               
        }

 ....
    }

DriverContext class

 public class DriverContext {

      public WebDriver Driver { get; set; }
      public DriverContext ()
        {

        }

    public void StartDriver()
    {
       Driver=new ChromeDriver();
    }
....
}

Your Step Class

[Binding]
public class TestSteps
{

    private DriverContext _driverContext;

    public TestSteps(DriverContext driverContext)
    {
        _driverContext= driverContext;
    }


}