在 SpecFlow 测试中使用 ChromeDriver
Using ChromeDriver across SpecFlow Tests
据我们所知,当您使用 SpecFlow 时,如果您重用另一个测试中的一个步骤,它会自动将其拉入并重用它...但是,我有一个问题,即测试 A 登录我,测试 B 登录,然后确认主页是正确的,但是当测试 A 正在初始化 Chrome 驱动程序时,当我开始使用测试 B 时,我的驱动程序想要打开另一个网页,导致测试失败,因为它打开了一个空网页。
我的问题是 - 如何在不打开 Chrome 的另一个实例的情况下使用驱动程序。这是我的 'generic login:'
代码
private LandingPageCode landingPage;
private HomePageCode HomePage;
[Given(@"I have entered my username, password selected login")]
public void GivenIHaveEnteredMyUsernamePasswordSelectedLogin()
{
driver = new ChromeDriver();
driver.Url = ("my URL");
landingPage = new LandingPageCode(driver);
HomePage = new HomePageCode(driver);
我在测试 B 上的代码在登录后验证主页:
{
private ChromeDriver driver;
private HomePageCode HomePage;
private LandingPageCode landingPage;
[Given(@"Successfully log into Cal's website (.*)")]
public void GivenSuccessfullyLogIntoOptix(Decimal p0)
{
driver = new ChromeDriver();
HomePage = new HomePageCode(driver);
landingPage = new LandingPageCode(driver);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
Assert.AreEqual("HomePage", driver.Title);
您可以从测试中删除您的驱动程序代码,并为您的代码设置一个框架 运行。使用 NUnit,您可以为自己开发一个框架来 运行 并行测试。网上有很多教程。 [https://nunit.org/][1]
您可以创建一个看起来像这样的 driver.cs class,它从配置 class 中提取基础 URL。:
public static class Driver
{
public static IWebDriver driver = new ChromeDriver();
public static void InitializedDriver()
{
Driver.driver.Navigate().GoToUrl(Config.BaseURL);
Driver.driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
}
}
然后在你的测试中 class,你可以使用 OneTimeSetUp 来初始化你的网络驱动程序:
[OneTimeSetUp]
public void Initialize()
{
Driver.InitializedDriver();
}
在你的测试代码之后,你可以使用:
[OneTimeTearDown]
public void CleanUp()
{
Driver.driver.Quit();
}
这将允许您的测试在同一个 Chrome 实例上 运行。
我经常看到这个问题或相关问题 ()。集成 Selenium 和 SpecFlow 可能很棘手。您需要利用 SpecFlow 自带的依赖注入框架,使用 before 和 after scenario hooks 来初始化 web driver,然后将其注册到依赖注入容器中。稍后在您的步骤定义 classes 中,您需要为那些接受 IWebDriver
对象作为构造函数参数的 classes 指定构造函数,并将其分配给每个步骤的字段定义 class.
[Binding]
public class WebDriverHooks
{
private readonly IObjectContainer container;
public WebDriverHooks(IObjectContainer container)
{
this.container = container;
}
[BeforeScenario]
public void CreateWebDriver()
{
// or new FirefoxDriver or new WhateverDriver as long as it implements
// the IWebDriver interface
ChromeDriver driver = new ChromeDriver();
// 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();
}
}
}
以及示例步骤定义文件:
[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");
}
}
这不仅允许您跨步骤定义文件共享 Web 驱动程序实例,而且它集中了创建和处理这些对象的逻辑,使您更接近允许并行测试执行。
另请参阅:Context Injection SpecFlow.org。
据我们所知,当您使用 SpecFlow 时,如果您重用另一个测试中的一个步骤,它会自动将其拉入并重用它...但是,我有一个问题,即测试 A 登录我,测试 B 登录,然后确认主页是正确的,但是当测试 A 正在初始化 Chrome 驱动程序时,当我开始使用测试 B 时,我的驱动程序想要打开另一个网页,导致测试失败,因为它打开了一个空网页。
我的问题是 - 如何在不打开 Chrome 的另一个实例的情况下使用驱动程序。这是我的 'generic login:'
代码 private LandingPageCode landingPage;
private HomePageCode HomePage;
[Given(@"I have entered my username, password selected login")]
public void GivenIHaveEnteredMyUsernamePasswordSelectedLogin()
{
driver = new ChromeDriver();
driver.Url = ("my URL");
landingPage = new LandingPageCode(driver);
HomePage = new HomePageCode(driver);
我在测试 B 上的代码在登录后验证主页:
{
private ChromeDriver driver;
private HomePageCode HomePage;
private LandingPageCode landingPage;
[Given(@"Successfully log into Cal's website (.*)")]
public void GivenSuccessfullyLogIntoOptix(Decimal p0)
{
driver = new ChromeDriver();
HomePage = new HomePageCode(driver);
landingPage = new LandingPageCode(driver);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
Assert.AreEqual("HomePage", driver.Title);
您可以从测试中删除您的驱动程序代码,并为您的代码设置一个框架 运行。使用 NUnit,您可以为自己开发一个框架来 运行 并行测试。网上有很多教程。 [https://nunit.org/][1]
您可以创建一个看起来像这样的 driver.cs class,它从配置 class 中提取基础 URL。:
public static class Driver
{
public static IWebDriver driver = new ChromeDriver();
public static void InitializedDriver()
{
Driver.driver.Navigate().GoToUrl(Config.BaseURL);
Driver.driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
}
}
然后在你的测试中 class,你可以使用 OneTimeSetUp 来初始化你的网络驱动程序:
[OneTimeSetUp]
public void Initialize()
{
Driver.InitializedDriver();
}
在你的测试代码之后,你可以使用:
[OneTimeTearDown]
public void CleanUp()
{
Driver.driver.Quit();
}
这将允许您的测试在同一个 Chrome 实例上 运行。
我经常看到这个问题或相关问题 (IWebDriver
对象作为构造函数参数的 classes 指定构造函数,并将其分配给每个步骤的字段定义 class.
[Binding]
public class WebDriverHooks
{
private readonly IObjectContainer container;
public WebDriverHooks(IObjectContainer container)
{
this.container = container;
}
[BeforeScenario]
public void CreateWebDriver()
{
// or new FirefoxDriver or new WhateverDriver as long as it implements
// the IWebDriver interface
ChromeDriver driver = new ChromeDriver();
// 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();
}
}
}
以及示例步骤定义文件:
[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");
}
}
这不仅允许您跨步骤定义文件共享 Web 驱动程序实例,而且它集中了创建和处理这些对象的逻辑,使您更接近允许并行测试执行。
另请参阅:Context Injection SpecFlow.org。