在 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。