如何在Selenium C#中不指定Chrome DevTools版本避免测试中断
问题
在项目中使用Selenium DevTools的Network日志工具简化测试分析,但目前必须在using语句中指定Chrome的具体版本(如示例中的V122)。公司IT部门会定期更新Chrome,导致DevTools版本与Chrome版本不匹配,测试执行中断。
请问是否存在无需指定特定版本的实现方式,让Chrome更新后测试不会立即崩溃?
技术栈
- Selenium 4
- .NET 6
当前代码
using DevToolsSessionDomains = OpenQA.Selenium.DevTools.V122.DevToolsSessionDomains; public class ChromeBrowser : MyBrowser { private static readonly ILogger _log = Serilog.Log.ForContext<ChromeBrowser>(); private ChromeDriver driver; public override void InitDriver(bool runHeadless) { new DriverManager().SetUpDriver(new ChromeConfig(), VersionResolveStrategy.MatchingBrowser); var service = ChromeDriverService.CreateDefaultService(); driver = new ChromeDriver(service, DriverOptions(runHeadless), TimeSpan.FromMinutes(3)); pid = service.ProcessId; _log.Information($"ChromeDriver PID = {pid}"); _log.Information($"Chrome capabilities: {driver.Capabilities}"); EnableLogging(); } public void EnableLogging() { if (!Properties.NetworkLogger) { //No logger is enabled _log.Information("No logging of network activity will be done during this test run."); return; } driver.ExecuteCdpCommand("Network.enable", new Dictionary<string, object>()); var session = driver.GetDevToolsSession(); var domains = session.GetVersionSpecificDomains<DevToolsSessionDomains>(); domains.Network.Enable(new EnableCommandSettings()); _log.Information("Logging of network activity has started."); domains.Network.RequestWillBeSent += RequestSentHandler; domains.Network.ResponseReceived += ResponseReceivedHandler; } public static void ResponseReceivedHandler(object sender, ResponseReceivedEventArgs e) { //logging responses given if (MimeTypes.ExcludedFromLogs.Exists(m => e.Response.MimeType.Contains(m))) { return; } string logLine = $"Status: {e.Response.Status}\tType: {e.Response.MimeType}\tUrl: {e.Response.Url}"; if (!MimeTypes.ExcludedFromBodyLogs.Exists(m => e.Response.MimeType.Contains(m))) { LogMessageBody(e.RequestId); } if (e.Response.Status != 200) { _log.Warning(logLine); } else { _log.Information(logLine); } } private static void LogMessageBody(string requestId) { var chromeDriver = TestBrowser.Browser as ChromeDriver; var session = chromeDriver.GetDevToolsSession(); var domains = session.GetVersionSpecificDomains<DevToolsSessionDomains>(); var settings = new GetResponseBodyCommandSettings { RequestId = requestId }; var command = domains.Network.GetResponseBody(settings); if (command.IsCompletedSuccessfully) { var body = command.Result; if (body != null && !string.IsNullOrEmpty(body.Body)) { _log.Information($"Body for requestId {requestId}"); _log.Information(body.Body); } } } public static void RequestSentHandler(object sender, RequestWillBeSentEventArgs e) { if (!(e.Request.HasPostData ?? false)) { return; } //logging requests made string logLine = $"Method: {e.Request.Method}\tRequest sent:{e.Request.PostData}"; _log.Information(logLine); } }
解决方案
核心思路:使用Selenium DevTools的通用抽象层
Selenium 4提供了不绑定特定Chrome版本的DevTools API,只需移除版本特定的引用,改用通用域对象即可自动匹配当前浏览器版本。
具体步骤
移除版本特定的依赖与引用
- 删除项目中针对特定版本的NuGet包(如
OpenQA.Selenium.DevTools.V122),只保留OpenQA.Selenium.DevTools包 - 删除版本特定的using语句:
using DevToolsSessionDomains = OpenQA.Selenium.DevTools.V122.DevToolsSessionDomains;
- 删除项目中针对特定版本的NuGet包(如
修改代码使用通用DevTools域
替换所有版本特定的GetVersionSpecificDomains调用,改用GetDomain<T>获取通用的Network域对象,示例修改如下:
修改后的EnableLogging方法
using OpenQA.Selenium.DevTools.Network; public async void EnableLogging() { if (!Properties.NetworkLogger) { _log.Information("本次测试不会记录网络活动日志。"); return; } var session = driver.GetDevToolsSession(); // 获取通用的Network域,自动匹配浏览器版本 var networkDomain = session.GetDomain<Network>(); await networkDomain.Enable(new EnableCommandSettings()); _log.Information("网络活动日志已开始记录。"); networkDomain.RequestWillBeSent += RequestSentHandler; networkDomain.ResponseReceived += ResponseReceivedHandler; }
修改后的LogMessageBody方法
private static async void LogMessageBody(string requestId) { var chromeDriver = TestBrowser.Browser as ChromeDriver; var session = chromeDriver.GetDevToolsSession(); var networkDomain = session.GetDomain<Network>(); var settings = new GetResponseBodyCommandSettings { RequestId = requestId }; var commandResult = await networkDomain.GetResponseBody(settings); if (commandResult != null && !string.IsNullOrEmpty(commandResult.Body)) { _log.Information($"请求ID {requestId} 的响应体:"); _log.Information(commandResult.Body); } }
修改事件处理器的参数类型
确保事件处理器的参数使用通用命名空间下的类型:
public static void ResponseReceivedHandler(object sender, OpenQA.Selenium.DevTools.Network.ResponseReceivedEventArgs e) { // 原有逻辑不变 } public static void RequestSentHandler(object sender, OpenQA.Selenium.DevTools.Network.RequestWillBeSentEventArgs e) { // 原有逻辑不变 }
- 保留DriverManager的版本匹配策略
你已经在使用VersionResolveStrategy.MatchingBrowser确保ChromeDriver版本与浏览器一致,继续保留这部分逻辑即可。
效果
修改后,Selenium会自动检测当前Chrome的版本,并匹配对应的DevTools协议实现,无需手动指定版本,Chrome更新后测试不会因版本不匹配而崩溃。
内容的提问来源于stack exchange,提问作者Jurn
相关产品推荐
相关产品推荐

