如何基于C#+NUnit+Selenium Grid实现单节点多浏览器并行测试
单个节点实现同一TestFixture多浏览器并行执行方案
针对你需要在单个Selenium Grid节点上并行运行同一TestFixture的Chrome和Firefox实例的需求,结合你给出的技术栈(C# + WebDriver 3.4.0 + NUnit 3.5.0 + Page Object+Page Factory模式),我整理了完整的实现方案和关键细节,帮你搞定并行执行:
先确认技术栈版本匹配
- 核心依赖:Selenium WebDriver 3.4.0、NUnit 3.5.0、Selenium Grid
- 浏览器驱动:ChromeDriver 2.36(对应Chrome 63-65)、Geckodriver 0.20.0(对应Firefox 57+)
- 目标浏览器:最新版Chrome、Firefox
完整代码实现
基类 BaseObject.cs(封装驱动初始化与清理)
using OpenQA.Selenium; using OpenQA.Selenium.Remote; using NUnit.Framework; using System; namespace YourTestProjectNamespace { public class BaseObject { protected IWebDriver Driver; // 初始化驱动的通用方法,接收浏览器名称参数 protected void SetupDriver(string browserName) { DesiredCapabilities capabilities = new DesiredCapabilities(); switch(browserName.ToLower()) { case "chrome": capabilities.SetCapability(CapabilityType.BrowserName, "chrome"); // 配置Chrome启动参数,比如最大化窗口 capabilities.SetCapability("chromeOptions", new { args = new[] { "start-maximized" } }); break; case "firefox": capabilities.SetCapability(CapabilityType.BrowserName, "firefox"); capabilities.SetCapability("moz:firefoxOptions", new { args = new[] { "--start-maximized" } }); break; default: throw new ArgumentException($"不支持的浏览器类型:{browserName}"); } // 连接到本地Grid节点(请根据你的Grid实际地址修改) Driver = new RemoteWebDriver(new Uri("http://localhost:4444/wd/hub"), capabilities); } [TearDown] public void CleanupDriver() { // 确保驱动正常关闭释放资源 Driver?.Quit(); Driver?.Dispose(); } } }
测试类 LoginTests.cs(核心并行配置)
using NUnit.Framework; namespace YourTestProjectNamespace { // 为每个浏览器创建独立的TestFixture实例 [TestFixture("chrome")] [TestFixture("firefox")] // 启用Fixture级别的并行执行:不同Fixture实例同时运行 [Parallelizable(ParallelScope.Fixtures)] public class LoginTests : BaseObject { private readonly string _targetBrowser; // 构造函数接收浏览器参数,传递给基类的驱动初始化方法 public LoginTests(string browserName) { _targetBrowser = browserName; } [SetUp] public void TestSetup() { SetupDriver(_targetBrowser); // 初始化Page Object(符合你的Page Factory模式) // var loginPage = PageFactory.InitElements<LoginPage>(Driver); } [Test] public void ValidLogin_ShouldRedirectToDashboard() { Driver.Navigate().GoToUrl("https://your-test-site.com/login"); // 替换为你的Page Object操作逻辑 // loginPage.EnterUsername("valid_user"); // loginPage.EnterPassword("valid_pass"); // loginPage.ClickLoginButton(); Assert.IsTrue(Driver.Url.Contains("dashboard"), "登录后未成功跳转到仪表盘"); } [Test] public void InvalidLogin_ShouldShowErrorMessage() { Driver.Navigate().GoToUrl("https://your-test-site.com/login"); // Page Object操作示例 // loginPage.EnterUsername("invalid_user"); // loginPage.EnterPassword("invalid_pass"); // loginPage.ClickLoginButton(); Assert.IsTrue(Driver.FindElement(By.CssSelector(".error-alert")).Displayed, "未显示预期的错误提示"); } } }
关键配置解析
- 参数化TestFixture:
通过[TestFixture("chrome")]和[TestFixture("firefox")],让NUnit为同一个测试类生成两个独立的Fixture实例,分别对应Chrome和Firefox。 - 并行执行开关:
[Parallelizable(ParallelScope.Fixtures)]是实现并行的核心——它告诉NUnit可以同时运行不同的Fixture实例,这样两个浏览器的测试就能在单个Grid节点上并行启动。 - Grid节点启动配置:
确保你的Grid节点已经正确注册,并且配置了驱动路径,启动命令示例:java -Dwebdriver.chrome.driver="C:/drivers/chromedriver.exe" -Dwebdriver.gecko.driver="C:/drivers/geckodriver.exe" -jar selenium-server-standalone-3.4.0.jar -role node -hub http://localhost:4444/grid/register
避坑提示
- 测试用例要保证无状态:不要在不同测试方法或Fixture之间共享数据,避免并行时互相干扰。
- 驱动与浏览器版本要匹配:你用的ChromeDriver 2.36对应Chrome 63-65,Geckodriver 0.20.0对应Firefox 57+,别搞混版本导致启动失败。
- Grid节点并发限制:默认配置下节点允许多个会话并行,如果你需要调整并发数,可以修改节点的配置文件。
内容的提问来源于stack exchange,提问作者Damir Heso
相关产品推荐
相关产品推荐

