每次测试后,我目前正在使用以下代码关闭浏览器:
[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;
}
答案 0 :(得分:0)
一个灯具中的NUnit测试都共享该灯具的相同实例。这是程序员必须牢记的NUnit设计的基本原理之一,因为测试很容易通过使用共享状态来互相踩踏。即使在非并行情况下,您也必须提防彼此干扰的测试,但是并行会使情况更糟。
在您的情况下,最可能的罪魁祸首是灯具的Driver属性。它由每个测试的设置 设置,并且保存在其中的所有内容由每个测试关闭。那不是你想要的。
我还注意到,驱动程序定义了两次,一次在灯具中,一次在基类中。您尚未发布足够的代码让我理解您为什么这样做,但这似乎有问题。
您必须确定夹具中的所有测试是否都打算使用相同的驱动程序。我怀疑这不是您想要的,因为驱动程序本身可能具有可变状态。但是,您可以使用任何一种方式进行设置。
要对所有测试使用相同的驱动程序,请使其成为灯具的属性。使用OneTimeSetUp方法初始化它,然后使用OneTimeTearDown方法释放它。
要对每个测试使用不同的驱动程序,请不要将其设置为属性。而是在每个测试中初始化局部变量,然后在测试本身中释放它。