【问题标题】:when using chromedriver, with specflow, a new browser instance open per step当使用带有specflow的chromedriver时,每一步都会打开一个新的浏览器实例
【发布时间】:2020-03-12 03:38:44
【问题描述】:

我遇到了 Specflow 的问题。出于某种原因,每一步都会启动一个新的 chrome 实例。 你能帮忙吗?

对于后续测试,启动 3 个步骤,3 个 chrome 实例。

Feature: Home

Background: 
Given The  QA Department site

Scenario: QA Department title 
    When QA site open
    Then QA site tile must be "UI Testing Site"

第一个实例有我想要的内容,但另外两个,我不知道为什么要启动,是空的。

namespace QAtests.SpecFlow_Steps.Home
{


     using NUnit.Framework;
     using System;
     using System.Collections.Generic;
     using System.Linq;
     using System.Text;
     using TechTalk.SpecFlow;

    [Binding]
     class HomeTestSteps
    {
        private readonly MainPage mainPage = new MainPage();
        private readonly PageHelper pageHelper = new PageHelper();

        public HomeTestSteps()
        {

        }

        [When(@"QA Department site open")]
        public void GivenQADepartmentSiteOpen()
        {
            var url = this.mainPage.ValiteSiteAddress();
            Assert.AreEqual(url, this.mainPage.siteURL);
        }


        [Then(@"QA Department site tile must be ""(.*)""")]
        public void ThenQADepartmentSiteTileMustBe(string pageTile)
        {
            var title = this.pageHelper.GetElementTitle();
            Assert.AreEqual(pageTile, title);
        }

    }
}

主页类只是设置url和检查元素


namespace QAtests.Pages.Main
{
    public class MainPage
    {

        private ChromeDriver driver = new ChromeDriver();
        private readonly string elementTitle = "//title";
        public readonly string siteURL = "http://uitest.duodecadits.com/";

        public MainPage()
        {

        }


        public void StartSite()
        {
            try
            {
                this.driver.Navigate().GoToUrl(siteURL);
            }
            catch (Exception e)
            {
                throw new Exception("Can´t set address.", e);
            }

        }

        public void Close()
        {
            this.driver.Close();
        }

        public string ValiteSiteAddress()
        {
            return this.driver.Url;
        }

        public IWebElement ElementTitleisVisible()
        {
            try
            {
                return this.driver.FindElement(By.XPath(elementTitle));
            }
            catch(Exception e){
                throw new Exception("Element tile not found.", e);
            }

        }
    }
}

我认为这与

的声明有关
private ChromeDriver driver = new ChromeDriver();

【问题讨论】:

    标签: c# selenium selenium-chromedriver specflow


    【解决方案1】:

    每次实例化页面时,您都会实例化一个新的 ChromeDriver 实例。

    按照建议,您需要在BeforeScenario 步骤中设置您的网络驱动程序。

    此外,您可以使用内置的 IOC 容器并注册您的 Web 驱动程序实例。然后可以在需要时将该实例注入到您的任何页面对象中。

    类似...

    [Binding]
    public class BaseScenarioHooks
    {
        protected IObjectContainer Container;
    
        public BaseScenarioHooks(IObjectContainer container)
        {
            Container = container;
        }
    
        [BeforeScenario(Order = 3)]
        public void SetupDrivers()
        {
            var webDriver = new WebDriver(browser, seleniumHub, url, Context.ScenarioInfo.Title,
                Context["UniqueTestName"].ToString(), FrameworkConfiguration.VideoRecording);
    
            Container.RegisterInstanceAs<WebDriver>(webDriver);
        }
    }
    

    看看https://github.com/techtalk/SpecFlow/wiki/Context-Injection

    还可以查看here,了解如何组织您的驱动程序类

    【讨论】:

      【解决方案2】:

      没有看到你的帖子在这里得到很多爱。老实说,我会在网上寻找一个 SpecFlow 框架,然后从那里开始构建你的框架。 SpecFlow 使用钩子,因此您可能希望使用 BeforeScenario 调用浏览器,以便为每个测试调用一次。将您的清理工作放在 AfterScenario 挂钩中。

      如果您使用 nuget chromedriver 并将其设置为始终输出到您的 bin 调试文件夹,则可以使用 GetBasePath 调用,以便它始终从该目录调用。不过,您可以删除调用并对 chromedrive.exe 路径进行硬编码。如果要进入源代码管理,这只会使其变得更容易。

      希望这将帮助您入门。

      例如

      我的文件.cs

        [BeforeScenario]
        public static void Startup()
        {
        Browser.StartWebDriver();
      
        }
      

      浏览器.cs

       public class Browser
       {
          static IWebDriver _Driver;
          static WebDriverWait _wait;
      
        public static void StartWebDriver()
        {
                      ChromeDriverService service = ChromeDriverService.CreateDefaultService(Path.Combine(GetBasePath, @"bin\Debug\"));
                      ChromeOptions options = new ChromeOptions();
                      options.AddArguments("--disable-extensions");
                      options.AddAdditionalCapability("useAutomationExtension", false);
                      options.AddExcludedArgument("enable-automation");
                      _Driver = new ChromeDriver(service, options);
                      _wait = new WebDriverWait(_Driver, TimeSpan.FromSeconds(10));
      
      
        }
      
      
      
      
          public static string GetBasePath
          {
              get
              {
                  var basePath =
                      System.IO.Path.GetDirectoryName((System.Reflection.Assembly.GetExecutingAssembly().Location));
                  basePath = basePath.Substring(0, basePath.Length - 10);
                  return basePath;
              }
          }
        }
      

      【讨论】:

        【解决方案3】:

        是的。这一行

        private ChromeDriver driver = new ChromeDriver();
        

        绝对是你的问题。每次访问此属性时,您都在创建一个新驱动程序。

        这是我在测试中使用的网络钩子类。

        [Binding]
        internal sealed class WebHooks
        {
            private readonly IObjectContainer _objectContainer;
        
            public WebHooks(IObjectContainer objectContainer)
            {
                _objectContainer = objectContainer;
            }
        
            [BeforeScenario("web")]
            public void BeforeWebScenario()
            {
                var options = new ChromeOptions();
                options.AddArgument("--start-maximized");
                options.AddAdditionalCapability("useAutomationExtension", false);
                options.AddArgument("no-sandbox");
        
                //HACK: this fixes issue with not being able to find chromedriver.exe
                //https://stackoverflow.com/questions/47910244/selenium-cant-find-chromedriver-exe
                var webDriver = new ChromeDriver(".", options);
                webDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
        
                _objectContainer.RegisterInstanceAs<IWebDriver>(webDriver);
            }
        
            [AfterScenario("web")]
            public void AfterWebScenario()
            {
                var webDriver = _objectContainer.Resolve<IWebDriver>();
        
                if (webDriver == null) return;
        
                webDriver.Close();
                webDriver.Dispose();
            }
        }
        

        因此,这会将 webdriver 注册到内部 SpecFlow DI 容器,以便现在可以在您的步骤定义中调用它。

        然后修改你的步骤定义类以访问webdriver作为构造函数参数

        [Binding]
        public class YourSteps
        {
            private readonly IWebDriver _webDriver;
        
            public CanvasSteps(IWebDriver webDriver)
            {
                _webDriver = webDriver;
            }
        }
        

        Specflow 的内部 DI 自动将所有内容连接起来,现在每个场景应该有 1 个 webdriver 实例。它还创建了一个更好的设计,因为您的 webdriver 实例的横切关注点已从您的步骤中提取并放置在所属的 Hook 中。只需使用 @web 钩子标记您的场景

        【讨论】:

          猜你喜欢
          • 2011-07-02
          • 1970-01-01
          • 2022-07-29
          • 1970-01-01
          • 2013-05-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多