【问题标题】:Running all tests in parallel fails with invalid session id并行运行所有测试失败,会话 ID 无效
【发布时间】:2019-07-30 17:52:02
【问题描述】:

我在一个测试类中有 4 个测试,当我分别运行每个测试时,它们都通过了。但是,当我并行运行它们时,它们会失败。我相信问题在于使用相同的驱动程序实例进行测试。我已将驱动程序更改为受保护,但结果是一样的。并行测试失败。

WebDriver 类:

using OpenQA.Selenium;

namespace TestAutomationFramework.Utilities
{
    public class WebDriver
    {
        protected IWebDriver Driver { get; set; }

    }
}

TestSetup 类:

using System;
using NUnit.Framework;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Remote;
using TestAutomationFramework.Utilities;

namespace TestAutomationFramework.Tests
{
    [TestFixture]
    public class TestSetup : WebDriver
    {
        public TestSetup()
        {
            var options = new ChromeOptions();
            Driver = new RemoteWebDriver(new Uri("http://localhost:4444/wd/hub"), options.ToCapabilities(), TimeSpan.FromSeconds(10));
            Driver.Manage().Window.Maximize();
        }

        // Test Setup, every test starts with this method
        [SetUp]
        public void StartTest()
        {
            Driver.Navigate().GoToUrl("https://google.com");
        }

        // Test Tear Down, every test ends with this method
        [TearDown]
        public void QuitTest()
        {
            Driver.Close();
            Driver.Quit();
        }
    }
}

BasePage 类:

using System.Threading;
using OpenQA.Selenium;

namespace TestAutomationFramework.Pages
{
    public class BasePage
    {
        protected IWebDriver WebDriver;
        public BasePage(IWebDriver webDriver) => WebDriver = webDriver;

        #region Elements
        private IWebElement SearchField => WebDriver.FindElement(By.Name("q"));
        private IWebElement SearchButton => WebDriver.FindElement(By.Name("btnK"));

        #endregion

        public void SearchFor(string searchText)
        {
            //Thread.Sleep(2000);
            SearchField.SendKeys(searchText);
            SearchButton.Click();
            Thread.Sleep(5000);
        }

        public bool SearchResultShows(string whatShows)
        {
            Thread.Sleep(5000);
            var element = WebDriver.FindElement(By.XPath(
                "//*[@id='rhs_block']/div/div[1]/div/div[1]/div[2]/div[1]/div[2]/div[2]/div/div/div[2]/div/span"));
            return element.Text.Equals(whatShows);
        }
    }
}

DemoTest 类

using NUnit.Framework;
using TestAutomationFramework.Pages;

namespace TestAutomationFramework.Tests
{
    [TestFixture]
    [Parallelizable(ParallelScope.All)]
    public class DemoTest : TestSetup
    {
        private BasePage _basePage;

        [Test]
        public void TestLogin()
        {
            const string query = "Test automation";
            _basePage = new BasePage(webDriver: Driver);
            _basePage.SearchFor(query);
            var shows = _basePage.SearchResultShows(whatShows: query);
            Assert.IsTrue(shows);
        }

        [Test]
        public void TestLogin2()
        {
            const string query = "Test automation";
            _basePage = new BasePage(webDriver: Driver);
            _basePage.SearchFor(query);
            var shows = _basePage.SearchResultShows(whatShows: query);
            Assert.IsTrue(shows);
        }

        [Test]
        public void TestLogin3()
        {
            const string query = "Test automation";
            _basePage = new BasePage(webDriver: Driver);
            _basePage.SearchFor(query);
            var shows = _basePage.SearchResultShows(whatShows: query);
            Assert.IsTrue(shows);
        }

        [Test]
        public void TestLogin4()
        {
            const string query = "Test automation";
            _basePage = new BasePage(webDriver: Driver);
            _basePage.SearchFor(query);
            var shows = _basePage.SearchResultShows(whatShows: query);
            Assert.IsTrue(shows);
        }
    }
}

问题:如何解决驱动实例,使所有测试不使用同一个驱动?

【问题讨论】:

    标签: c# selenium


    【解决方案1】:

    根据Does NUnit create a new instance of the test fixture class for each contained test method nowadays?,测试类实例对于所有测试都是相同的。 Driver 实例在第一个测试运行后立即被销毁(在方法 QuitTest 中),因此另一个测试将不再有驱动程序。

    试试这个:

    [TestFixture]
    public class TestSetup
    {
       private ThreadLocal<IWebDriver> _driver;
    
       protected IWebDriver Driver => _driver.Value;
    
       // Test Setup, every test starts with this method
       [SetUp]
       public void StartTest()        
       {
           var options = new ChromeOptions();
           _driver = new ThreadLocal<IWebDriver>(() => new RemoteWebDriver(new Uri("http://localhost:4444/wd/hub"), options.ToCapabilities(), TimeSpan.FromSeconds(10)));
           Driver.Manage().Window.Maximize();
           Driver.Navigate().GoToUrl("https://google.com");
       }
    
       // Test Tear Down, every test ends with this method
       [TearDown]
       public void QuitTest()
       {
           Driver.Close();
           Driver.Quit();
           _driver.Dispose();
       }
    }
    

    这可能会因为TheadLocal 而影响性能。我不确定。

    【讨论】:

    • 感谢您的回答。您的解决方案有效,但正如您所说,我正在寻找并行执行。对此有何建议?
    • 傻我...我认为 xUnit 可以在同一个类中并行运行测试。这不可以。我会更新答案。
    【解决方案2】:

    您始终可以使用驱动程序制作字典,其中键是线程 ID,值是测试使用的驱动程序。

    private static Dictionary<int, IWebDriver> drivers = new Dictionary<int, IWebDriver();
    
    public static IWebDriver GetDriver()
    {
        int id = Thread.CurrentThread.ManagedThreadId;
        if (!drivers.Keys.Contains(id))
        {
            SetupNewDriver();
        }
        return drivers[id];
    }
    

    在创建驱动程序时将其添加到字典中(下一行来自 SetupDriver 方法):

    drivers.Add(Thread.CurrentThread.ManagedThreadId, driver);
    

    在我的项目中,我使用上面的代码创建了类 DriverManager,它可以工作。缺点是您将无法为一项测试运行多个驱动程序。有可能为驱动程序制作更复杂的结构,但我不需要这样做。

    【讨论】:

      猜你喜欢
      • 2021-02-18
      • 1970-01-01
      • 2020-04-08
      • 1970-01-01
      • 1970-01-01
      • 2015-02-19
      • 1970-01-01
      • 2011-05-09
      • 1970-01-01
      相关资源
      最近更新 更多