如何在使用SeleniumWebDriver和NUnitC#并行运行测试后关闭多个浏览器窗口



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

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

当运行单个测试时,这很好。但是,当我使用NUnit的[Palallelizable]标记在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 Firefoxfirefox.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代码

ObjectRepository.LoginButton.Click();

我不确定我设置测试的方式是否是导致问题的部分原因,但如果我能在这方面得到任何帮助,将不胜感激

编辑:在中添加了更多我的代码以帮助:

基本测试类别:

[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 Firefoxfirefox.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;

}

fixture中的NUnit测试都共享fixture的同一实例。这是NUnit设计的基本原理之一,程序员必须记住,因为通过使用共享状态,测试很容易相互干扰。即使在非并行的情况下,也必须注意测试之间的干扰,但并行会使情况变得更糟。

在您的情况下,最有可能的罪魁祸首是fixture的Driver属性。它由每个测试的设置设置,并且保持在那里的任何东西都由每个测试关闭。这不是你想要的。

我还注意到,Driver被定义了两次,一次在fixture中,另一次在基类中。你还没有发布足够的代码让我理解你为什么这么做,但这似乎有问题。

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

要对所有测试使用相同的驱动程序,请将其作为fixture的属性。在OneTimeSetUp方法中初始化它,并在OneTimeTearDown方法中释放它。

若要为每个测试使用不同的驱动程序,请不要将其作为属性。相反,在每个测试中初始化一个局部变量,并在测试本身中释放它。

相关内容

  • 没有找到相关文章

最新更新