使用Selenium WebDriver和NUnit C#在Parallel中运行测试后,如何关闭多个浏览器窗口

时间:2018-08-06 09:12:46

标签: c# selenium automated-tests nunit parallel-testing

每次测试后,我目前正在使用以下代码关闭浏览器:

    [TearDown]
    public void StopBrowser()
    {
            if (Driver == null)
                return;
            Driver.Quit();
    }

这在运行单个测试时很好用,但是当我使用NUnit的[Parallelizable]标记在Parallel中运行多个测试时,由于没有此类会话错误,我的测试开始失败,无法连接到远程服务器错误,然后对象引用错误排在最前面,因此绝对与并行测试有关。

请在下面找到我在[SetUp]方法中使用的代码:

    public IWebDriver Driver { get; set; }

    public string TestUrl;

    [SetUp]
    public void Setup()
    {
        string Browser = "Chrome";

        if (Browser == "Chrome")
        {
            ChromeOptions options = new ChromeOptions();
            options.AddArgument("--start-maximized");
            Driver = new ChromeDriver(options);
        }
        else if (Browser == "Firefox")
        {
            FirefoxDriverService service = FirefoxDriverService.CreateDefaultService();
            service.FirefoxBinaryPath = @"C:\Program Files (x86)\Mozilla Firefox\firefox.exe";
            Driver = new FirefoxDriver(service);
        }
        else if (Browser == "Edge")
        {
            EdgeDriverService service = EdgeDriverService.CreateDefaultService();
            Driver = new EdgeDriver(service);
        }

BasePage代码:

    public class BasePage<TObjectRepository> where TObjectRepository : BasePageObjectRepository
    {

        public BasePage(IWebDriver driver, TObjectRepository repository)
        {
            Driver = driver;
            ObjectRepository = repository;
        }



        public IWebDriver Driver { get; }
        internal TObjectRepository ObjectRepository { get; }
    }

BasePageObjectRepository代码:

public class BasePageObjectRepository
{
    protected readonly IWebDriver Driver;

    public BasePageObjectRepository(IWebDriver driver)
    {
        Driver = driver;
    }
}

“我的测试”仅在其相关页面内调用特定函数,然后页面内的代码仅具有Selenium代码,该代码指向该Pages对象存储库中的元素,即

ObjectRepository.LoginButton.Click();

我不确定我的测试设置方式是否是部分导致问题的原因,但是对此我能提供的任何帮助将不胜感激

编辑:添加了更多我的代码以提供帮助:

BaseTest类:

    [TestFixture]
public class BaseTest
{
    public IWebDriver Driver { get; set; }

    public string TestUrl;


    [SetUp]
    public void Setup()
    {
        string Browser = "Chrome";

        if (Browser == "Chrome")
        {
            ChromeOptions options = new ChromeOptions();
            options.AddArgument("--start-maximized");
            Driver = new ChromeDriver(options);
        }
        else if (Browser == "Firefox")
        {
            FirefoxDriverService service = FirefoxDriverService.CreateDefaultService();
            service.FirefoxBinaryPath = @"C:\Program Files (x86)\Mozilla Firefox\firefox.exe";
            Driver = new FirefoxDriver(service);
        }
        else if (Browser == "Edge")
        {
            EdgeDriverService service = EdgeDriverService.CreateDefaultService();
            Driver = new EdgeDriver(service);
        }

        Driver.Manage().Window.Maximize();

        string Environment;
        Environment = "Test";



        if (Environment == "Test")
        {
            TestUrl = "https://walberton-test.azurewebsites.net/";
        }
        else if (Environment == "Live")
        {
            TestUrl = "";
        }

     }
}

[OneTimeTearDown]
public void TeardownAllBrowsers()
{
    Driver.Close();
    Driver.Quit();
}

其中一项测试的示例:

[TestFixture]
public class TimeLogsTestChrome: BaseTest
{
    [Test]
    [Parallelizable]
    [Category("Time Logs Test for Chrome")]
    public void AssertTimeLogsHeading()
    {
        Driver = new ChromeDriver();
        Driver.Manage().Window.Maximize();
        var loginPage = new LoginPage(Driver);
        var dashboard = new Dashboard(Driver);
        var timeSheets = new Timesheets(Driver);
        loginPage.GoTo("Test");
        loginPage.EnterEmailAddress("Valid");
        loginPage.EnterPassword("Valid");
        loginPage.ClickLoginButtonForLoginToDashboard();
        dashboard.ClickTimesheetsButton();
        timeSheets.AssertHeading();
        Driver.Close();
    }
}

测试基础代码的示例:

internal class Timesheets : BasePage<TimesheetsPageObjectRepository>
{

    public Timesheets(IWebDriver driver) : base(driver, new TimesheetsPageObjectRepository(driver))
    {
    }

    internal void AssertHeading()
    {
        try
        {
            Assert.AreEqual("Timesheets", ObjectRepository.TimesheetHeading);
        }
        catch (Exception ex)
        {
            throw;
        }
    }

    internal void ClickAddTimesheetButton()
    {
        ObjectRepository.AddTimesheetButton.Click();
    }

    internal void ClickSubmitTimeButton()
    {
        ObjectRepository.SubmitTimeButton.Click();
        Thread.Sleep(5000);
    }
}

具有大多数FindElement代码的页面对象存储库的部分示例:

internal class TimesheetsPageObjectRepository : BasePageObjectRepository
{

    public TimesheetsPageObjectRepository(IWebDriver driver) : base(driver) { }

    public string TimesheetHeading => Driver.FindElement(By.ClassName("pull-left")).Text;

}

1 个答案:

答案 0 :(得分:0)

一个灯具中的NUnit测试都共享该灯具的相同实例。这是程序员必须牢记的NUnit设计的基本原理之一,因为测试很容易通过使用共享状态来互相踩踏。即使在非并行情况下,您也必须提防彼此干扰的测试,但是并行会使情况更糟。

在您的情况下,最可能的罪魁祸首是灯具的Driver属性。它由每个测试的设置 设置,并且保存在其中的所有内容由每个测试关闭。那不是你想要的。

我还注意到,驱动程序定义了两次,一次在灯具中,一次在基类中。您尚未发布足够的代码让我理解您为什么这样做,但这似乎有问题。

您必须确定夹具中的所有测试是否都打算使用相同的驱动程序。我怀疑这不是您想要的,因为驱动程序本身可能具有可变状态。但是,您可以使用任何一种方式进行设置。

要对所有测试使用相同的驱动程序,请使其成为灯具的属性。使用OneTimeSetUp方法初始化它,然后使用OneTimeTearDown方法释放它。

要对每个测试使用不同的驱动程序,请不要将其设置为属性。而是在每个测试中初始化局部变量,然后在测试本身中释放它。