【问题标题】:Using ChromeDriver across SpecFlow Tests在 SpecFlow 测试中使用 ChromeDriver
【发布时间】:2020-02-13 00:31:18
【问题描述】:

所以我们知道,当您使用 SpecFlow 时,如果您重用另一个测试中的一个步骤,它会自动将其拉入并重用它......但是,我遇到了一个问题,即测试 A 让我登录,测试 B 登录并确认主页是正确的,但是当我开始使用测试 B 时,测试 A 正在初始化 ChromeDriver,我的驱动程序想要打开另一个网页,导致测试失败,因为它打开了一个空网页。

我的问题是 - 如何在不打开另一个 Chrome 实例的情况下使用驱动程序。这是我的“通用登录”代码明智的:

        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);

【问题讨论】:

    标签: c# .net selenium-webdriver selenium-chromedriver specflow


    【解决方案1】:

    我经常看到这个问题或相关问题 (How to properly manage and access webdriver instances to avoid problems with parallel execution of tests?)。集成 Selenium 和 SpecFlow 可能很棘手。您需要利用 SpecFlow 附带的依赖注入框架,并使用 before 和 after 场景挂钩来初始化 Web 驱动程序,然后将其注册到依赖注入容器中。稍后在您的步骤定义类中,您需要为那些接受IWebDriver 对象作为构造函数参数的类指定构造函数,并将其分配给每个步骤定义类的字段。

    [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 驱动程序实例,而且它集中了创建和处置这些对象的逻辑,并让您更接近允许并行测试执行。

    另请参阅:SpecFlow.org 上的 Context Injection。

    【讨论】:

      【解决方案2】:

      您可以从测试中删除您的驱动程序代码,并为您的代码设置一个框架来运行。使用 NUnit,您可以为自己开发一个框架来并行运行测试。有很多关于此的在线教程。 [https://nunit.org/][1]

      您可以创建一个如下所示的 driver.cs 类,该类从配置类中提取基本 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);
          }
      }
      

      然后在你的测试类中,你可以使用 OneTimeSetUp 来初始化你的网络驱动:

          [OneTimeSetUp]
         public void Initialize()
          {
              Driver.InitializedDriver();
          }
      

      在你的测试代码之后,你可以使用:

              [OneTimeTearDown]
          public void CleanUp()
          {
              Driver.driver.Quit();
      
          }
      

      这将允许您的测试在同一个 Chrome 实例上运行。

      【讨论】:

      • 您好,谢谢,我们目前在 NUnit 中有另一个项目,并且正在探索其他选项,因此我需要使用 SpecFlow 的解决方案 :)
      • medium.com/asos-techblog/… 这个链接可能会有所帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多