Having Multiple Step Files Opens Multiple BrowsersTroubles with [After*] Fixtures in StepsCatch multiple exceptions at once?How to create Excel (.XLS and .XLSX) file in C# without installing Ms Office?Selenium concern with Coding Practicessymfony2 / behat / mink login troubles when testing in the browser<Cucumber-JVM> pass values between steps in cucumberChrome driver 2.24 is not working with Chrome browser version 54Webdriver can login in Chrome, not in firefox: 'Unable to find owning document' errorError: 'value': keys_to_typing(value)} while sending keys selenium pythonTroubles with [After*] Fixtures in Steps
If human space travel is limited by the G force vulnerability, is there a way to counter G forces?
How do I gain back my faith in my PhD degree?
Is it possible to create a QR code using text?
Can my sorcerer use a spellbook only to collect spells and scribe scrolls, not cast?
What do you call someone who asks many questions?
Is it logically or scientifically possible to artificially send energy to the body?
Detention in 1997
How would I stat a creature to be immune to everything but the Magic Missile spell? (just for fun)
One verb to replace 'be a member of' a club
What method can I use to design a dungeon difficult enough that the PCs can't make it through without killing them?
How can saying a song's name be a copyright violation?
Unlock My Phone! February 2018
Probability that a draw from a normal distribution is some number greater than another draw from the same distribution
Do scales need to be in alphabetical order?
Unable to supress ligatures in headings which are set in Caps
What about the virus in 12 Monkeys?
Determining Impedance With An Antenna Analyzer
Is there a hemisphere-neutral way of specifying a season?
Why doesn't using multiple commands with a || or && conditional work?
What are some good books on Machine Learning and AI like Krugman, Wells and Graddy's "Essentials of Economics"
GFCI outlets - can they be repaired? Are they really needed at the end of a circuit?
Valid term from quadratic sequence?
Is "remove commented out code" correct English?
Short story with a alien planet, government officials must wear exploding medallions
Having Multiple Step Files Opens Multiple Browsers
Troubles with [After*] Fixtures in StepsCatch multiple exceptions at once?How to create Excel (.XLS and .XLSX) file in C# without installing Ms Office?Selenium concern with Coding Practicessymfony2 / behat / mink login troubles when testing in the browser<Cucumber-JVM> pass values between steps in cucumberChrome driver 2.24 is not working with Chrome browser version 54Webdriver can login in Chrome, not in firefox: 'Unable to find owning document' errorError: 'value': keys_to_typing(value)} while sending keys selenium pythonTroubles with [After*] Fixtures in Steps
The Problem:
If I have more than one Steps file, when I execute tests it seems that the WebDriver creation for each is being happening regardless of which test(s) I run.
I was seeing a seemingly random Chrome Browser open up whenever I ran my tests. In an attempt to see if there was some sort of incompatibility between SpecFlow and ChromeDriver (a long shot, I know), I changed the WebDriver for my search tests to Firefox and left the WebDriver for my login tests as Chrome. No matter what test(s) I ran, I always saw 2 browsers open; one Chrome and one Firefox.
When I moved all of the steps from my SearchTestSteps.cs file into the LoginTestSteps.cs file, the problem disappeared.
So, yeah, this solves the immediate issue, but it is sub-optimal to have all of my steps in a single file. That can quickly become unwieldy.
Since each set of steps needs to have its own WebDriver, I'm at a loss.
Might this have something to do with folder structure and where things are stored? Here is what mine looks like.
Root
|-Page Object Files
|- Page Components
|- Pages
|- Test Tools
|- Step Definitions
|- <*Steps.cs>
|- TESTS
|- BDD Tests
|-<*.feature>
|- *standard selenium test files*
The Code:
Login.feature
Feature: Login
In order to be able to use Laserfiche
As a legitimate user
I want to be able to log into the repository
@SmokeTest
Scenario: Login with correct credentials
Given I am on the Login page
And I have a good username/password combination
And I select a repository
When I fill out the form and submit
Then I am taken to the repo page
---------------
LoginSteps.cs (I also have a SearchTestSteps.cs that looks very similar)
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Selenium_C_Sharp_POC.Page_Object_Files.Pages;
using Selenium_C_Sharp_POC.Page_Object_Files.Test_Tools;
using TechTalk.SpecFlow;
namespace Selenium_C_Sharp_POC.StepDefinitions
[Binding]
public class LoginSteps
private static readonly IWebDriver Driver = new ChromeDriver();
private static LoginPage _loginPage;
private static string _username;
private static string _password;
private static string _repo;
[AfterTestRun]
public static void ShutDown()
Driver?.Close();
[Given(@"I am on the Login page")]
public void GivenIAmOnTheLoginPage()
_loginPage = new LoginPage(Driver);
[Given(@"I have a good username/password combination")]
public void GivenIHaveAGoodUsernamePasswordCombination()
_username = Nomenclature.WebClientPersonalUsername;
_password = Nomenclature.WebClientPersonalPassword;
[Given(@"I select a repository")]
public void GivenISelectARepository()
_repo = Nomenclature.RepoUnderTest;
[When(@"I fill out the form and submit")]
public void WhenIFillOutTheFormAndSubmit()
_loginPage.Login(
username: _username,
password: _password,
repo: _repo);
[Then(@"I am taken to the repo page")]
public void ThenIAmTakenToTheRepoPage()
Assert.AreEqual(
expected: _repo,
actual: Driver.Title);
HelperMethods.Logout(Driver);
c# selenium selenium-webdriver bdd specflow
add a comment |
The Problem:
If I have more than one Steps file, when I execute tests it seems that the WebDriver creation for each is being happening regardless of which test(s) I run.
I was seeing a seemingly random Chrome Browser open up whenever I ran my tests. In an attempt to see if there was some sort of incompatibility between SpecFlow and ChromeDriver (a long shot, I know), I changed the WebDriver for my search tests to Firefox and left the WebDriver for my login tests as Chrome. No matter what test(s) I ran, I always saw 2 browsers open; one Chrome and one Firefox.
When I moved all of the steps from my SearchTestSteps.cs file into the LoginTestSteps.cs file, the problem disappeared.
So, yeah, this solves the immediate issue, but it is sub-optimal to have all of my steps in a single file. That can quickly become unwieldy.
Since each set of steps needs to have its own WebDriver, I'm at a loss.
Might this have something to do with folder structure and where things are stored? Here is what mine looks like.
Root
|-Page Object Files
|- Page Components
|- Pages
|- Test Tools
|- Step Definitions
|- <*Steps.cs>
|- TESTS
|- BDD Tests
|-<*.feature>
|- *standard selenium test files*
The Code:
Login.feature
Feature: Login
In order to be able to use Laserfiche
As a legitimate user
I want to be able to log into the repository
@SmokeTest
Scenario: Login with correct credentials
Given I am on the Login page
And I have a good username/password combination
And I select a repository
When I fill out the form and submit
Then I am taken to the repo page
---------------
LoginSteps.cs (I also have a SearchTestSteps.cs that looks very similar)
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Selenium_C_Sharp_POC.Page_Object_Files.Pages;
using Selenium_C_Sharp_POC.Page_Object_Files.Test_Tools;
using TechTalk.SpecFlow;
namespace Selenium_C_Sharp_POC.StepDefinitions
[Binding]
public class LoginSteps
private static readonly IWebDriver Driver = new ChromeDriver();
private static LoginPage _loginPage;
private static string _username;
private static string _password;
private static string _repo;
[AfterTestRun]
public static void ShutDown()
Driver?.Close();
[Given(@"I am on the Login page")]
public void GivenIAmOnTheLoginPage()
_loginPage = new LoginPage(Driver);
[Given(@"I have a good username/password combination")]
public void GivenIHaveAGoodUsernamePasswordCombination()
_username = Nomenclature.WebClientPersonalUsername;
_password = Nomenclature.WebClientPersonalPassword;
[Given(@"I select a repository")]
public void GivenISelectARepository()
_repo = Nomenclature.RepoUnderTest;
[When(@"I fill out the form and submit")]
public void WhenIFillOutTheFormAndSubmit()
_loginPage.Login(
username: _username,
password: _password,
repo: _repo);
[Then(@"I am taken to the repo page")]
public void ThenIAmTakenToTheRepoPage()
Assert.AreEqual(
expected: _repo,
actual: Driver.Title);
HelperMethods.Logout(Driver);
c# selenium selenium-webdriver bdd specflow
add a comment |
The Problem:
If I have more than one Steps file, when I execute tests it seems that the WebDriver creation for each is being happening regardless of which test(s) I run.
I was seeing a seemingly random Chrome Browser open up whenever I ran my tests. In an attempt to see if there was some sort of incompatibility between SpecFlow and ChromeDriver (a long shot, I know), I changed the WebDriver for my search tests to Firefox and left the WebDriver for my login tests as Chrome. No matter what test(s) I ran, I always saw 2 browsers open; one Chrome and one Firefox.
When I moved all of the steps from my SearchTestSteps.cs file into the LoginTestSteps.cs file, the problem disappeared.
So, yeah, this solves the immediate issue, but it is sub-optimal to have all of my steps in a single file. That can quickly become unwieldy.
Since each set of steps needs to have its own WebDriver, I'm at a loss.
Might this have something to do with folder structure and where things are stored? Here is what mine looks like.
Root
|-Page Object Files
|- Page Components
|- Pages
|- Test Tools
|- Step Definitions
|- <*Steps.cs>
|- TESTS
|- BDD Tests
|-<*.feature>
|- *standard selenium test files*
The Code:
Login.feature
Feature: Login
In order to be able to use Laserfiche
As a legitimate user
I want to be able to log into the repository
@SmokeTest
Scenario: Login with correct credentials
Given I am on the Login page
And I have a good username/password combination
And I select a repository
When I fill out the form and submit
Then I am taken to the repo page
---------------
LoginSteps.cs (I also have a SearchTestSteps.cs that looks very similar)
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Selenium_C_Sharp_POC.Page_Object_Files.Pages;
using Selenium_C_Sharp_POC.Page_Object_Files.Test_Tools;
using TechTalk.SpecFlow;
namespace Selenium_C_Sharp_POC.StepDefinitions
[Binding]
public class LoginSteps
private static readonly IWebDriver Driver = new ChromeDriver();
private static LoginPage _loginPage;
private static string _username;
private static string _password;
private static string _repo;
[AfterTestRun]
public static void ShutDown()
Driver?.Close();
[Given(@"I am on the Login page")]
public void GivenIAmOnTheLoginPage()
_loginPage = new LoginPage(Driver);
[Given(@"I have a good username/password combination")]
public void GivenIHaveAGoodUsernamePasswordCombination()
_username = Nomenclature.WebClientPersonalUsername;
_password = Nomenclature.WebClientPersonalPassword;
[Given(@"I select a repository")]
public void GivenISelectARepository()
_repo = Nomenclature.RepoUnderTest;
[When(@"I fill out the form and submit")]
public void WhenIFillOutTheFormAndSubmit()
_loginPage.Login(
username: _username,
password: _password,
repo: _repo);
[Then(@"I am taken to the repo page")]
public void ThenIAmTakenToTheRepoPage()
Assert.AreEqual(
expected: _repo,
actual: Driver.Title);
HelperMethods.Logout(Driver);
c# selenium selenium-webdriver bdd specflow
The Problem:
If I have more than one Steps file, when I execute tests it seems that the WebDriver creation for each is being happening regardless of which test(s) I run.
I was seeing a seemingly random Chrome Browser open up whenever I ran my tests. In an attempt to see if there was some sort of incompatibility between SpecFlow and ChromeDriver (a long shot, I know), I changed the WebDriver for my search tests to Firefox and left the WebDriver for my login tests as Chrome. No matter what test(s) I ran, I always saw 2 browsers open; one Chrome and one Firefox.
When I moved all of the steps from my SearchTestSteps.cs file into the LoginTestSteps.cs file, the problem disappeared.
So, yeah, this solves the immediate issue, but it is sub-optimal to have all of my steps in a single file. That can quickly become unwieldy.
Since each set of steps needs to have its own WebDriver, I'm at a loss.
Might this have something to do with folder structure and where things are stored? Here is what mine looks like.
Root
|-Page Object Files
|- Page Components
|- Pages
|- Test Tools
|- Step Definitions
|- <*Steps.cs>
|- TESTS
|- BDD Tests
|-<*.feature>
|- *standard selenium test files*
The Code:
Login.feature
Feature: Login
In order to be able to use Laserfiche
As a legitimate user
I want to be able to log into the repository
@SmokeTest
Scenario: Login with correct credentials
Given I am on the Login page
And I have a good username/password combination
And I select a repository
When I fill out the form and submit
Then I am taken to the repo page
---------------
LoginSteps.cs (I also have a SearchTestSteps.cs that looks very similar)
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using Selenium_C_Sharp_POC.Page_Object_Files.Pages;
using Selenium_C_Sharp_POC.Page_Object_Files.Test_Tools;
using TechTalk.SpecFlow;
namespace Selenium_C_Sharp_POC.StepDefinitions
[Binding]
public class LoginSteps
private static readonly IWebDriver Driver = new ChromeDriver();
private static LoginPage _loginPage;
private static string _username;
private static string _password;
private static string _repo;
[AfterTestRun]
public static void ShutDown()
Driver?.Close();
[Given(@"I am on the Login page")]
public void GivenIAmOnTheLoginPage()
_loginPage = new LoginPage(Driver);
[Given(@"I have a good username/password combination")]
public void GivenIHaveAGoodUsernamePasswordCombination()
_username = Nomenclature.WebClientPersonalUsername;
_password = Nomenclature.WebClientPersonalPassword;
[Given(@"I select a repository")]
public void GivenISelectARepository()
_repo = Nomenclature.RepoUnderTest;
[When(@"I fill out the form and submit")]
public void WhenIFillOutTheFormAndSubmit()
_loginPage.Login(
username: _username,
password: _password,
repo: _repo);
[Then(@"I am taken to the repo page")]
public void ThenIAmTakenToTheRepoPage()
Assert.AreEqual(
expected: _repo,
actual: Driver.Title);
HelperMethods.Logout(Driver);
c# selenium selenium-webdriver bdd specflow
c# selenium selenium-webdriver bdd specflow
asked Mar 8 at 22:20
Eddy JonesEddy Jones
515
515
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
I figured out how to fix this issue using Binding Scopes.
In each of the Steps files, I can do the following:
[BeforeFeature(), Scope(Feature = "SearchTests")]
public static void Startup()
_driver = new ChromeDriver();
[AfterFeature()]
public static void ShutDown()
_driver?.Close();
Doing this opens and closes the Driver for only the Test file that I want it to.
I can also choose to scope to the tag before each test if I need to get more granular.
Cool. But I would recommend to create a browser_steps.cs with "open" method. With in the method check if driver is nil then create the driver instance based on the browser you pass to the method or in the global variable. By this way you don't have to handle the driver startup and tear down in each of the step.cs file.
– supputuri
Mar 9 at 14:04
that was my reluctance to do it this way as well. I have created a baseSteps class that has the driver creations with before and after feature methods... So far everything is working perfectly.
– Eddy Jones
Mar 11 at 17:06
Cool. All the best!
– supputuri
Mar 11 at 17:10
add a comment |
You might have created driver instance in each of the .cs files.
Eg: In the LoginSteps.cs you are creating chrome driver in the below loc.
private static readonly IWebDriver Driver = new ChromeDriver();
You should create the driver outside the xStep.cs files and just pass it to the class/method based on the framework.
I guess this is where my newness to SpecFlow comes in. How do I pass a driver to the steps file from the Gherkin. There doesn't seem to be a way to do that.
– Eddy Jones
Mar 8 at 23:25
To be frank I don't have much hands on with SpecFlow, but you have to use "before scenario" or "hooks". Sorry, I am not able to provide more insight. Check this link SpecFlow Documentation
– supputuri
Mar 8 at 23:37
add a comment |
Ultimately this is being caused by creating the web drivers as static fields on your step definition classes. You need to centralize this logic.
You want to create your web driver before the feature, register it with the SpecFlow dependency injection container, and then pass that IWebDriver object around to your step definitions.
I found it a good idea to implement a "lazy" web driver, so the browser window only gets spawned when your C# code actually needs to interact with it. This LazyWebDriver class implements the IWebDriver interface, and is a wrapper for a real web driver.
LazyWebDriver.cs
public sealed class LazyWebDriver : IWebDriver
private readonly Lazy<IWebDriver> driver;
public string Title => driver.Value.Title;
// Other properties defined in IWebDriver just pass through to driver.Value.Property
public LazyWebDriver(Func<IWebDriver> driverFactory)
driver = new Lazy<IWebDriver>(driverFactory);
public IWebElement FindElement(By by)
return driver.Value.FindElement(by);
public void Close()
driver.Value.Close();
// other methods defined in IWebDriver just pass through to driver.Value.Method(...)
Then using SpecFlow hooks (which is just fancy-talk for "events" in SpecFlow) you can create your real web driver and the lazy web driver and register it with the SpecFlow framework:
SeleniumHooks.cs
[Binding]
public sealed class SeleniumHooks
private readonly IObjectContainer objectContainer;
public SeleniumHooks(IObjectContainer objectContainer)
this.objectContainer = objectContainer;
[BeforeFeature]
public void RegisterWebDriver()
objectContainer.RegisterInstanceAs<IWebDriver>(new LazyWebDriver(CreateWebDriver));
private IWebDriver CreateWebDriver()
return new ChromeDriver();
[AfterFeature]
public void DestroyWebDriver()
objectContainer.Resolve<IWebDriver>()?.Close();
Lastly, a few modifications to your LoginSteps.cs file:
[Binding]
public class LoginSteps
private readonly IWebDriver Driver;
private LoginPage _loginPage;
private static string _username;
private static string _password;
private static string _repo;
public LoginSteps(IWebDriver driver)
Driver = driver;
[Given(@"I am on the Login page")]
public void GivenIAmOnTheLoginPage()
_loginPage = new LoginPage(Driver);
[Given(@"I have a good username/password combination")]
public void GivenIHaveAGoodUsernamePasswordCombination()
_username = Nomenclature.WebClientPersonalUsername;
_password = Nomenclature.WebClientPersonalPassword;
[Given(@"I select a repository")]
public void GivenISelectARepository()
_repo = Nomenclature.RepoUnderTest;
[When(@"I fill out the form and submit")]
public void WhenIFillOutTheFormAndSubmit()
_loginPage.Login(
username: _username,
password: _password,
repo: _repo);
[Then(@"I am taken to the repo page")]
public void ThenIAmTakenToTheRepoPage()
Assert.AreEqual(
expected: _repo,
actual: Driver.Title);
HelperMethods.Logout(Driver);
Notice that the IWebDriver object is passed in as a constructor argument to LoginSteps. SpecFlow comes with a dependency injection framework, which is smart enough to pass the LazyWebDriver you registered in SeleniumHooks as the IWebDriver argument to the LoginSteps constructor.
Be sure to make the _loginPage field an instance field rather than static.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55071795%2fhaving-multiple-step-files-opens-multiple-browsers%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
I figured out how to fix this issue using Binding Scopes.
In each of the Steps files, I can do the following:
[BeforeFeature(), Scope(Feature = "SearchTests")]
public static void Startup()
_driver = new ChromeDriver();
[AfterFeature()]
public static void ShutDown()
_driver?.Close();
Doing this opens and closes the Driver for only the Test file that I want it to.
I can also choose to scope to the tag before each test if I need to get more granular.
Cool. But I would recommend to create a browser_steps.cs with "open" method. With in the method check if driver is nil then create the driver instance based on the browser you pass to the method or in the global variable. By this way you don't have to handle the driver startup and tear down in each of the step.cs file.
– supputuri
Mar 9 at 14:04
that was my reluctance to do it this way as well. I have created a baseSteps class that has the driver creations with before and after feature methods... So far everything is working perfectly.
– Eddy Jones
Mar 11 at 17:06
Cool. All the best!
– supputuri
Mar 11 at 17:10
add a comment |
I figured out how to fix this issue using Binding Scopes.
In each of the Steps files, I can do the following:
[BeforeFeature(), Scope(Feature = "SearchTests")]
public static void Startup()
_driver = new ChromeDriver();
[AfterFeature()]
public static void ShutDown()
_driver?.Close();
Doing this opens and closes the Driver for only the Test file that I want it to.
I can also choose to scope to the tag before each test if I need to get more granular.
Cool. But I would recommend to create a browser_steps.cs with "open" method. With in the method check if driver is nil then create the driver instance based on the browser you pass to the method or in the global variable. By this way you don't have to handle the driver startup and tear down in each of the step.cs file.
– supputuri
Mar 9 at 14:04
that was my reluctance to do it this way as well. I have created a baseSteps class that has the driver creations with before and after feature methods... So far everything is working perfectly.
– Eddy Jones
Mar 11 at 17:06
Cool. All the best!
– supputuri
Mar 11 at 17:10
add a comment |
I figured out how to fix this issue using Binding Scopes.
In each of the Steps files, I can do the following:
[BeforeFeature(), Scope(Feature = "SearchTests")]
public static void Startup()
_driver = new ChromeDriver();
[AfterFeature()]
public static void ShutDown()
_driver?.Close();
Doing this opens and closes the Driver for only the Test file that I want it to.
I can also choose to scope to the tag before each test if I need to get more granular.
I figured out how to fix this issue using Binding Scopes.
In each of the Steps files, I can do the following:
[BeforeFeature(), Scope(Feature = "SearchTests")]
public static void Startup()
_driver = new ChromeDriver();
[AfterFeature()]
public static void ShutDown()
_driver?.Close();
Doing this opens and closes the Driver for only the Test file that I want it to.
I can also choose to scope to the tag before each test if I need to get more granular.
answered Mar 8 at 23:28
Eddy JonesEddy Jones
515
515
Cool. But I would recommend to create a browser_steps.cs with "open" method. With in the method check if driver is nil then create the driver instance based on the browser you pass to the method or in the global variable. By this way you don't have to handle the driver startup and tear down in each of the step.cs file.
– supputuri
Mar 9 at 14:04
that was my reluctance to do it this way as well. I have created a baseSteps class that has the driver creations with before and after feature methods... So far everything is working perfectly.
– Eddy Jones
Mar 11 at 17:06
Cool. All the best!
– supputuri
Mar 11 at 17:10
add a comment |
Cool. But I would recommend to create a browser_steps.cs with "open" method. With in the method check if driver is nil then create the driver instance based on the browser you pass to the method or in the global variable. By this way you don't have to handle the driver startup and tear down in each of the step.cs file.
– supputuri
Mar 9 at 14:04
that was my reluctance to do it this way as well. I have created a baseSteps class that has the driver creations with before and after feature methods... So far everything is working perfectly.
– Eddy Jones
Mar 11 at 17:06
Cool. All the best!
– supputuri
Mar 11 at 17:10
Cool. But I would recommend to create a browser_steps.cs with "open" method. With in the method check if driver is nil then create the driver instance based on the browser you pass to the method or in the global variable. By this way you don't have to handle the driver startup and tear down in each of the step.cs file.
– supputuri
Mar 9 at 14:04
Cool. But I would recommend to create a browser_steps.cs with "open" method. With in the method check if driver is nil then create the driver instance based on the browser you pass to the method or in the global variable. By this way you don't have to handle the driver startup and tear down in each of the step.cs file.
– supputuri
Mar 9 at 14:04
that was my reluctance to do it this way as well. I have created a baseSteps class that has the driver creations with before and after feature methods... So far everything is working perfectly.
– Eddy Jones
Mar 11 at 17:06
that was my reluctance to do it this way as well. I have created a baseSteps class that has the driver creations with before and after feature methods... So far everything is working perfectly.
– Eddy Jones
Mar 11 at 17:06
Cool. All the best!
– supputuri
Mar 11 at 17:10
Cool. All the best!
– supputuri
Mar 11 at 17:10
add a comment |
You might have created driver instance in each of the .cs files.
Eg: In the LoginSteps.cs you are creating chrome driver in the below loc.
private static readonly IWebDriver Driver = new ChromeDriver();
You should create the driver outside the xStep.cs files and just pass it to the class/method based on the framework.
I guess this is where my newness to SpecFlow comes in. How do I pass a driver to the steps file from the Gherkin. There doesn't seem to be a way to do that.
– Eddy Jones
Mar 8 at 23:25
To be frank I don't have much hands on with SpecFlow, but you have to use "before scenario" or "hooks". Sorry, I am not able to provide more insight. Check this link SpecFlow Documentation
– supputuri
Mar 8 at 23:37
add a comment |
You might have created driver instance in each of the .cs files.
Eg: In the LoginSteps.cs you are creating chrome driver in the below loc.
private static readonly IWebDriver Driver = new ChromeDriver();
You should create the driver outside the xStep.cs files and just pass it to the class/method based on the framework.
I guess this is where my newness to SpecFlow comes in. How do I pass a driver to the steps file from the Gherkin. There doesn't seem to be a way to do that.
– Eddy Jones
Mar 8 at 23:25
To be frank I don't have much hands on with SpecFlow, but you have to use "before scenario" or "hooks". Sorry, I am not able to provide more insight. Check this link SpecFlow Documentation
– supputuri
Mar 8 at 23:37
add a comment |
You might have created driver instance in each of the .cs files.
Eg: In the LoginSteps.cs you are creating chrome driver in the below loc.
private static readonly IWebDriver Driver = new ChromeDriver();
You should create the driver outside the xStep.cs files and just pass it to the class/method based on the framework.
You might have created driver instance in each of the .cs files.
Eg: In the LoginSteps.cs you are creating chrome driver in the below loc.
private static readonly IWebDriver Driver = new ChromeDriver();
You should create the driver outside the xStep.cs files and just pass it to the class/method based on the framework.
answered Mar 8 at 22:55
supputurisupputuri
1,1381612
1,1381612
I guess this is where my newness to SpecFlow comes in. How do I pass a driver to the steps file from the Gherkin. There doesn't seem to be a way to do that.
– Eddy Jones
Mar 8 at 23:25
To be frank I don't have much hands on with SpecFlow, but you have to use "before scenario" or "hooks". Sorry, I am not able to provide more insight. Check this link SpecFlow Documentation
– supputuri
Mar 8 at 23:37
add a comment |
I guess this is where my newness to SpecFlow comes in. How do I pass a driver to the steps file from the Gherkin. There doesn't seem to be a way to do that.
– Eddy Jones
Mar 8 at 23:25
To be frank I don't have much hands on with SpecFlow, but you have to use "before scenario" or "hooks". Sorry, I am not able to provide more insight. Check this link SpecFlow Documentation
– supputuri
Mar 8 at 23:37
I guess this is where my newness to SpecFlow comes in. How do I pass a driver to the steps file from the Gherkin. There doesn't seem to be a way to do that.
– Eddy Jones
Mar 8 at 23:25
I guess this is where my newness to SpecFlow comes in. How do I pass a driver to the steps file from the Gherkin. There doesn't seem to be a way to do that.
– Eddy Jones
Mar 8 at 23:25
To be frank I don't have much hands on with SpecFlow, but you have to use "before scenario" or "hooks". Sorry, I am not able to provide more insight. Check this link SpecFlow Documentation
– supputuri
Mar 8 at 23:37
To be frank I don't have much hands on with SpecFlow, but you have to use "before scenario" or "hooks". Sorry, I am not able to provide more insight. Check this link SpecFlow Documentation
– supputuri
Mar 8 at 23:37
add a comment |
Ultimately this is being caused by creating the web drivers as static fields on your step definition classes. You need to centralize this logic.
You want to create your web driver before the feature, register it with the SpecFlow dependency injection container, and then pass that IWebDriver object around to your step definitions.
I found it a good idea to implement a "lazy" web driver, so the browser window only gets spawned when your C# code actually needs to interact with it. This LazyWebDriver class implements the IWebDriver interface, and is a wrapper for a real web driver.
LazyWebDriver.cs
public sealed class LazyWebDriver : IWebDriver
private readonly Lazy<IWebDriver> driver;
public string Title => driver.Value.Title;
// Other properties defined in IWebDriver just pass through to driver.Value.Property
public LazyWebDriver(Func<IWebDriver> driverFactory)
driver = new Lazy<IWebDriver>(driverFactory);
public IWebElement FindElement(By by)
return driver.Value.FindElement(by);
public void Close()
driver.Value.Close();
// other methods defined in IWebDriver just pass through to driver.Value.Method(...)
Then using SpecFlow hooks (which is just fancy-talk for "events" in SpecFlow) you can create your real web driver and the lazy web driver and register it with the SpecFlow framework:
SeleniumHooks.cs
[Binding]
public sealed class SeleniumHooks
private readonly IObjectContainer objectContainer;
public SeleniumHooks(IObjectContainer objectContainer)
this.objectContainer = objectContainer;
[BeforeFeature]
public void RegisterWebDriver()
objectContainer.RegisterInstanceAs<IWebDriver>(new LazyWebDriver(CreateWebDriver));
private IWebDriver CreateWebDriver()
return new ChromeDriver();
[AfterFeature]
public void DestroyWebDriver()
objectContainer.Resolve<IWebDriver>()?.Close();
Lastly, a few modifications to your LoginSteps.cs file:
[Binding]
public class LoginSteps
private readonly IWebDriver Driver;
private LoginPage _loginPage;
private static string _username;
private static string _password;
private static string _repo;
public LoginSteps(IWebDriver driver)
Driver = driver;
[Given(@"I am on the Login page")]
public void GivenIAmOnTheLoginPage()
_loginPage = new LoginPage(Driver);
[Given(@"I have a good username/password combination")]
public void GivenIHaveAGoodUsernamePasswordCombination()
_username = Nomenclature.WebClientPersonalUsername;
_password = Nomenclature.WebClientPersonalPassword;
[Given(@"I select a repository")]
public void GivenISelectARepository()
_repo = Nomenclature.RepoUnderTest;
[When(@"I fill out the form and submit")]
public void WhenIFillOutTheFormAndSubmit()
_loginPage.Login(
username: _username,
password: _password,
repo: _repo);
[Then(@"I am taken to the repo page")]
public void ThenIAmTakenToTheRepoPage()
Assert.AreEqual(
expected: _repo,
actual: Driver.Title);
HelperMethods.Logout(Driver);
Notice that the IWebDriver object is passed in as a constructor argument to LoginSteps. SpecFlow comes with a dependency injection framework, which is smart enough to pass the LazyWebDriver you registered in SeleniumHooks as the IWebDriver argument to the LoginSteps constructor.
Be sure to make the _loginPage field an instance field rather than static.
add a comment |
Ultimately this is being caused by creating the web drivers as static fields on your step definition classes. You need to centralize this logic.
You want to create your web driver before the feature, register it with the SpecFlow dependency injection container, and then pass that IWebDriver object around to your step definitions.
I found it a good idea to implement a "lazy" web driver, so the browser window only gets spawned when your C# code actually needs to interact with it. This LazyWebDriver class implements the IWebDriver interface, and is a wrapper for a real web driver.
LazyWebDriver.cs
public sealed class LazyWebDriver : IWebDriver
private readonly Lazy<IWebDriver> driver;
public string Title => driver.Value.Title;
// Other properties defined in IWebDriver just pass through to driver.Value.Property
public LazyWebDriver(Func<IWebDriver> driverFactory)
driver = new Lazy<IWebDriver>(driverFactory);
public IWebElement FindElement(By by)
return driver.Value.FindElement(by);
public void Close()
driver.Value.Close();
// other methods defined in IWebDriver just pass through to driver.Value.Method(...)
Then using SpecFlow hooks (which is just fancy-talk for "events" in SpecFlow) you can create your real web driver and the lazy web driver and register it with the SpecFlow framework:
SeleniumHooks.cs
[Binding]
public sealed class SeleniumHooks
private readonly IObjectContainer objectContainer;
public SeleniumHooks(IObjectContainer objectContainer)
this.objectContainer = objectContainer;
[BeforeFeature]
public void RegisterWebDriver()
objectContainer.RegisterInstanceAs<IWebDriver>(new LazyWebDriver(CreateWebDriver));
private IWebDriver CreateWebDriver()
return new ChromeDriver();
[AfterFeature]
public void DestroyWebDriver()
objectContainer.Resolve<IWebDriver>()?.Close();
Lastly, a few modifications to your LoginSteps.cs file:
[Binding]
public class LoginSteps
private readonly IWebDriver Driver;
private LoginPage _loginPage;
private static string _username;
private static string _password;
private static string _repo;
public LoginSteps(IWebDriver driver)
Driver = driver;
[Given(@"I am on the Login page")]
public void GivenIAmOnTheLoginPage()
_loginPage = new LoginPage(Driver);
[Given(@"I have a good username/password combination")]
public void GivenIHaveAGoodUsernamePasswordCombination()
_username = Nomenclature.WebClientPersonalUsername;
_password = Nomenclature.WebClientPersonalPassword;
[Given(@"I select a repository")]
public void GivenISelectARepository()
_repo = Nomenclature.RepoUnderTest;
[When(@"I fill out the form and submit")]
public void WhenIFillOutTheFormAndSubmit()
_loginPage.Login(
username: _username,
password: _password,
repo: _repo);
[Then(@"I am taken to the repo page")]
public void ThenIAmTakenToTheRepoPage()
Assert.AreEqual(
expected: _repo,
actual: Driver.Title);
HelperMethods.Logout(Driver);
Notice that the IWebDriver object is passed in as a constructor argument to LoginSteps. SpecFlow comes with a dependency injection framework, which is smart enough to pass the LazyWebDriver you registered in SeleniumHooks as the IWebDriver argument to the LoginSteps constructor.
Be sure to make the _loginPage field an instance field rather than static.
add a comment |
Ultimately this is being caused by creating the web drivers as static fields on your step definition classes. You need to centralize this logic.
You want to create your web driver before the feature, register it with the SpecFlow dependency injection container, and then pass that IWebDriver object around to your step definitions.
I found it a good idea to implement a "lazy" web driver, so the browser window only gets spawned when your C# code actually needs to interact with it. This LazyWebDriver class implements the IWebDriver interface, and is a wrapper for a real web driver.
LazyWebDriver.cs
public sealed class LazyWebDriver : IWebDriver
private readonly Lazy<IWebDriver> driver;
public string Title => driver.Value.Title;
// Other properties defined in IWebDriver just pass through to driver.Value.Property
public LazyWebDriver(Func<IWebDriver> driverFactory)
driver = new Lazy<IWebDriver>(driverFactory);
public IWebElement FindElement(By by)
return driver.Value.FindElement(by);
public void Close()
driver.Value.Close();
// other methods defined in IWebDriver just pass through to driver.Value.Method(...)
Then using SpecFlow hooks (which is just fancy-talk for "events" in SpecFlow) you can create your real web driver and the lazy web driver and register it with the SpecFlow framework:
SeleniumHooks.cs
[Binding]
public sealed class SeleniumHooks
private readonly IObjectContainer objectContainer;
public SeleniumHooks(IObjectContainer objectContainer)
this.objectContainer = objectContainer;
[BeforeFeature]
public void RegisterWebDriver()
objectContainer.RegisterInstanceAs<IWebDriver>(new LazyWebDriver(CreateWebDriver));
private IWebDriver CreateWebDriver()
return new ChromeDriver();
[AfterFeature]
public void DestroyWebDriver()
objectContainer.Resolve<IWebDriver>()?.Close();
Lastly, a few modifications to your LoginSteps.cs file:
[Binding]
public class LoginSteps
private readonly IWebDriver Driver;
private LoginPage _loginPage;
private static string _username;
private static string _password;
private static string _repo;
public LoginSteps(IWebDriver driver)
Driver = driver;
[Given(@"I am on the Login page")]
public void GivenIAmOnTheLoginPage()
_loginPage = new LoginPage(Driver);
[Given(@"I have a good username/password combination")]
public void GivenIHaveAGoodUsernamePasswordCombination()
_username = Nomenclature.WebClientPersonalUsername;
_password = Nomenclature.WebClientPersonalPassword;
[Given(@"I select a repository")]
public void GivenISelectARepository()
_repo = Nomenclature.RepoUnderTest;
[When(@"I fill out the form and submit")]
public void WhenIFillOutTheFormAndSubmit()
_loginPage.Login(
username: _username,
password: _password,
repo: _repo);
[Then(@"I am taken to the repo page")]
public void ThenIAmTakenToTheRepoPage()
Assert.AreEqual(
expected: _repo,
actual: Driver.Title);
HelperMethods.Logout(Driver);
Notice that the IWebDriver object is passed in as a constructor argument to LoginSteps. SpecFlow comes with a dependency injection framework, which is smart enough to pass the LazyWebDriver you registered in SeleniumHooks as the IWebDriver argument to the LoginSteps constructor.
Be sure to make the _loginPage field an instance field rather than static.
Ultimately this is being caused by creating the web drivers as static fields on your step definition classes. You need to centralize this logic.
You want to create your web driver before the feature, register it with the SpecFlow dependency injection container, and then pass that IWebDriver object around to your step definitions.
I found it a good idea to implement a "lazy" web driver, so the browser window only gets spawned when your C# code actually needs to interact with it. This LazyWebDriver class implements the IWebDriver interface, and is a wrapper for a real web driver.
LazyWebDriver.cs
public sealed class LazyWebDriver : IWebDriver
private readonly Lazy<IWebDriver> driver;
public string Title => driver.Value.Title;
// Other properties defined in IWebDriver just pass through to driver.Value.Property
public LazyWebDriver(Func<IWebDriver> driverFactory)
driver = new Lazy<IWebDriver>(driverFactory);
public IWebElement FindElement(By by)
return driver.Value.FindElement(by);
public void Close()
driver.Value.Close();
// other methods defined in IWebDriver just pass through to driver.Value.Method(...)
Then using SpecFlow hooks (which is just fancy-talk for "events" in SpecFlow) you can create your real web driver and the lazy web driver and register it with the SpecFlow framework:
SeleniumHooks.cs
[Binding]
public sealed class SeleniumHooks
private readonly IObjectContainer objectContainer;
public SeleniumHooks(IObjectContainer objectContainer)
this.objectContainer = objectContainer;
[BeforeFeature]
public void RegisterWebDriver()
objectContainer.RegisterInstanceAs<IWebDriver>(new LazyWebDriver(CreateWebDriver));
private IWebDriver CreateWebDriver()
return new ChromeDriver();
[AfterFeature]
public void DestroyWebDriver()
objectContainer.Resolve<IWebDriver>()?.Close();
Lastly, a few modifications to your LoginSteps.cs file:
[Binding]
public class LoginSteps
private readonly IWebDriver Driver;
private LoginPage _loginPage;
private static string _username;
private static string _password;
private static string _repo;
public LoginSteps(IWebDriver driver)
Driver = driver;
[Given(@"I am on the Login page")]
public void GivenIAmOnTheLoginPage()
_loginPage = new LoginPage(Driver);
[Given(@"I have a good username/password combination")]
public void GivenIHaveAGoodUsernamePasswordCombination()
_username = Nomenclature.WebClientPersonalUsername;
_password = Nomenclature.WebClientPersonalPassword;
[Given(@"I select a repository")]
public void GivenISelectARepository()
_repo = Nomenclature.RepoUnderTest;
[When(@"I fill out the form and submit")]
public void WhenIFillOutTheFormAndSubmit()
_loginPage.Login(
username: _username,
password: _password,
repo: _repo);
[Then(@"I am taken to the repo page")]
public void ThenIAmTakenToTheRepoPage()
Assert.AreEqual(
expected: _repo,
actual: Driver.Title);
HelperMethods.Logout(Driver);
Notice that the IWebDriver object is passed in as a constructor argument to LoginSteps. SpecFlow comes with a dependency injection framework, which is smart enough to pass the LazyWebDriver you registered in SeleniumHooks as the IWebDriver argument to the LoginSteps constructor.
Be sure to make the _loginPage field an instance field rather than static.
edited 3 hours ago
answered 3 hours ago
Greg BurghardtGreg Burghardt
8,58163050
8,58163050
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55071795%2fhaving-multiple-step-files-opens-multiple-browsers%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown