2

I have implemented Specflow to reuse some steps across features as in this example -Specflow,Selenium-Share data between different Step definitions or classes .Since, in our project, we are integrating multiple features & reusing them. What is the best way to share browser session across features if its triggered in between steps as per the above approach?

My Scenario:

Once an application created, I need to launch new session, login different User-set different services and approve it.

But after logging in fails with below error on Step definition 4 in reused Whenstep of Given(Set the service to (.*)). That particular step is from different feature, hence the new session needs to be used in those steps. The LaunchURl method below is just launching the website with url, no new session created - This works fine

OpenQA.Selenium.WebDriverException : Unexpected error. System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it "IP here"

[Given(@"A New Application is added")]    
public void GivenANewApplicationIsAdded()
{
    Given("UK_The Service is set");
    Given("User Navigated to New Application screen");
    When("User fills up form as in data row 1");
    Then("new SID generated");
}

[Given(@"New Browser Launched")]
public void GivenNewBrowserLaunched()
{
    SeleniumContext sl = new SeleniumContext();
    this.seleniumContext = sl;
}


[Given(@"Login is successful with ""(.*)"" and ""(.*)""")]
public void GivenLoginIsSuccessfulWithAnd(string userName, string password)
{
    SuperTests spr = new SuperTests();
    _driver = spr.LaunchURL(seleniumContext.WebDriver);
    //seleniumContext.WebDriver = _driver;
    LoginPage lg = new LoginPage(_driver);
    lg.LoginProcess(userName, password);        
}

[Given(@"Set the service to ""(.*)""")]
public void GivenSetTheServiceTo(string serviceId)
{
    When("Select a Service from the option "+serviceId);
    Then("The Services is changed to the one selected " + serviceId);
}

In other feature

[When(@"Select a Service from the option (.*)")]    
public void WhenSelectAServiceFromTheOptionTestTeam(string p0)
{
    HomePage mst = new HomePage(seleniumContext.WebDriver);
    mst.SetServiceId(p0);
}

The 2 work around what we figured was Create a new instance of binding class to call the methods or steps as shown below

[Given(@"Set the service to ""(.*)""")]
public void GivenSetTheServiceTo(string serviceId)
{  
   var serIdSteps = new UK_SetServiceIDSteps(seleniumContext);
   serIdSteps.WhenUK_SelectAServiceFromTheOptionTest(serviceId);
   serIdSteps.ThenUK_TheServicesIsChangedToTheOneSelected(serviceId);
}

or

tried this which worked as well- basically calling a new method to create a new session. for this I need not create any new instance for Binding class. Called the Step directly.

[Given(@"New Browser Launched")]
            public void GivenNewBrowserLaunched()
            {
                SuperTests spr = new SuperTests();
                _driver = spr.LaunchURL("Firefox");
                seleniumContext.WebDriver = _driver;
            }

    public void GivenSetTheServiceTo(string serviceId)
            {
                When("UK_Select a Service from the option "+serviceId);
                    Then("UK_The Services is changed to the one selected " + serviceId);
            }

Not sure, which is correct way of doing it? Trying to figure it out from Reusable steps point?The latter one is not advised as we need to change the type of browser to launch at multiple place.

Community
  • 1
  • 1
ReuseAutomator
  • 410
  • 3
  • 14
  • are you passing the `seleniumContext` in to all steps classes via the constructor? – Sam Holder Aug 11 '15 at 08:36
  • @Sam-Yes, passing the seleniumContext via constructor in all step classes – ReuseAutomator Aug 11 '15 at 13:25
  • @Sam-Updated my query above with some work around code, the main reason we get the above error is due to the session being different to the prior time when constructor was executed. So basically, prior to executing the When step of GivenSetTheServiceTo, a step from the particular Binding class is already used.Hence the webdriver context is set to the one prior to new session creation. The query I have was how to set the ObjectContainer to store new WebDriver session & run the respective constructor. The above 2 updates are just a work around this issue. – ReuseAutomator Aug 12 '15 at 07:26
  • how was you selenimContext.WebDriver being set before? You probably want to do this in a before scenario hook which you also inject the scenario context into so you can set this once for the entire scenario. – Sam Holder Aug 12 '15 at 07:47
  • Similar to example above,setting the driver afterLaunchUrl method. I changed BeforeScenario hook to this,but did not work - [BeforeScenario] public void RunBeforeScenario() { objectContainer.RegisterInstanceAs(seleniumContext); _driver = seleniumContext.WebDriver; }. With respect to re usability, looks like the latter solution above is the only one which works, otherwise unable to use steps from features. – ReuseAutomator Aug 13 '15 at 04:02
  • @Sam-Also , we trying to launch new browser session in between a Scenario, not at the start of new scenario. Probably, not so sure on ObjectContainer part, maybe that needs disposed & re assigned again. – ReuseAutomator Aug 13 '15 at 04:35
  • you don't need to register the `seleniumContext` with the `objectContainer` unless your selenium context does not have a default constructor. Instead its better to ask for the `seleniumContext` in the constructor of the class with the `BeforeScenario` method in it. Are you sure that the problem is with the seleniumDriver as the issue you have is that the url is not reachable, which implies that the driver object is set up correctly, it's just the url that is wrong... – Sam Holder Aug 13 '15 at 12:07
  • Given that the first workaround works, this implies that the seleniumContext which is being passed into each step class by the DI system in specflow is not passing the same instance. I suspect this is because of something to do with your explicit use of the `objectContainer`. I would remove this and see if it helps fix the issue. – Sam Holder Aug 13 '15 at 12:17
  • also you could create a guid property on your seleniumContrext class which is set in the constructor to a new guid to see if thew instances are the same or not. If they are the same instances then the guids returned by the property will be the same. If they are different object instances then the guids will be different – Sam Holder Aug 13 '15 at 12:18
  • @Sam-the URL step is successful and logged in as per case 1, only thing is cannot call step definitions directly in proceeding steps. The object container is only set once in beforealltests class and registered before scenario. Checked the window handler I'd of driver which is same (different to previous prerequiste step which is expected)for new session and launch of URL.It throws exception when steps from different feature called-Example-When step above. – ReuseAutomator Aug 13 '15 at 13:29

0 Answers0