Вам необходимо использовать инфраструктуру внедрения зависимостей, которая поставляется с SpecFlow. Вариант № 2, где вы создаете его в [BeforeScenario]
и уничтожаете его в [AfterScenario]
, является правильным способом, но тогда вам нужно зарегистрировать объект IWebDriver
в каркасе внедрения зависимостей:
[Binding]
public class WebDriverHooks
{
private readonly IObjectContainer container;
public WebDriverHooks(IObjectContainer container)
{
this.container = container;
}
[BeforeScenario]
public void CreateWebDriver()
{
FirefoxDriver driver = new FirefoxDriver();
// Make 'driver' available for DI
container.RegisterInstanceAs<IWebDriver>(driver);
}
[AfterScenario]
public void DestroyWebDriver()
{
var driver = container.Resolve<IWebDriver>();
if (driver != null)
{
driver.Quit();
driver.Dispose();
}
}
}
Ваши определения шагов должны принимать объект IWebDriver в качестве аргумента конструктора. Вы даже можете зарегистрировать объекты вашей страницы в DI-фреймворке.
[Binding]
public class LoginSteps
{
private readonly IWebDriver driver;
private readonly LoginPage loginPage;
public LoginSteps(IWebDriver driver)
{
// Assign 'driver' to private field or use it to initialize a page object
this.driver = driver;
// Initialize Selenium page object
this.loginPage = new LoginPage(driver);
}
[When(@"I go to the login page")]
public void WhenIGoToTheLoginPage()
{
// Use 'driver' in step definition
driver.FindElement(By.LinkText("Sign In")).Click();
}
[When(@"I log in")]
public void WhenILogIn()
{
// Use Selenium page object in step definition
loginPage.LogIn("testUser", "testPassword");
}
}
В проекте GitHub, на который вы ссылались, объект веб-драйвера инициализируется как статическое свойство. Именно поэтому этот пример кода нельзя использовать для параллельных тестов. Похоже, что все выполняющиеся сценарии используют один и тот же домен приложения, поэтому они разделяют статическое состояние класса, что означает, что каждый сценарий пытается использовать один и тот же экземпляр браузера.