Azure DevOps流水线Selenium C#测试套件WebDriver异常求助
问题描述
近15天,基于Selenium C#的测试套件执行PDF打印命令时出现异常:本地及测试VM上手动通过Visual Studio运行正常,但在Azure DevOps流水线中执行失败。TearDown阶段触发OpenQA.Selenium.WebDriverException,提示向远程WebDriver服务器发送的HTTP请求超时60秒,嵌套异常包含System.Threading.Tasks.TaskCanceledException、System.IO.IOException及System.Net.Sockets.SocketException。已尝试升级/降级ChromeDriver版本、添加--no-sandbox和--no-gpu参数、延长超时时间、更新Selenium.Support及Selenium.WebDriver版本等方案,均未解决。
异常详情
TearDown : OpenQA.Selenium.WebDriverException : The HTTP request to the remote WebDriver server for URL http://localhost:54995/session/36a5bcb819c93c78746cf5eb6ca81796/goog/cdp/execute timed out after 60 seconds.
----> System.Threading.Tasks.TaskCanceledException : The operation was canceled.
----> System.IO.IOException : Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request..
----> System.Net.Sockets.SocketException : The I/O operation has been aborted because of either a thread exit or an application request.
堆栈跟踪:
--TearDown at OpenQA.Selenium.Remote.HttpCommandExecutor.ExecuteAsync(Command commandToExecute) at OpenQA.Selenium.Remote.DriverServiceCommandExecutor.ExecuteAsync(Command commandToExecute) at OpenQA.Selenium.WebDriver.ExecuteAsync(String driverCommandToExecute, Dictionary`2 parameters) at OpenQA.Selenium.WebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters) at OpenQA.Selenium.Chromium.ChromiumDriver.ExecuteCdpCommand(String commandName, Dictionary`2 commandParameters)
相关代码
public static byte[] ConvertHtmlToPdf(string html) { int t = 0; int timeout = 180; byte[] pdf = new byte[] { }; DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); string baseDir = di.Parent.Parent.Parent.FullName; string reportDir = Path.Combine(baseDir, "Report", BaseFixture.timestamp); var filePath = Path.Combine(reportDir, $"{Guid.NewGuid()}.html"); File.WriteAllTextAsync(filePath, html); var driverOptions = new ChromeOptions(); //In headless mode, PDF writing is enabled by default, hence switching to headless mode driverOptions.AddArgument("headless"); using var driver = new ChromeDriver(driverOptions); driver.Navigate().GoToUrl(filePath); // Output a PDF of the first page in A4 size at 90% scale var printOptions = new Dictionary<string, object> { { "paperWidth", 210 / 5 }, { "paperHeight", 150 / 5 }, { "scale", 0.9 }, { "pageRanges", "1-2" }, { "preferCSSPageSize", true } }; //while (t < timeout) //{ // Thread.Sleep(60000); // t = t + 60; var printOutput = driver.ExecuteCdpCommand("Page.printToPDF", printOptions) as Dictionary<string, object>; pdf = Convert.FromBase64String(printOutput["data"] as string); //} File.Delete(filePath); return pdf; }
解决方案建议
修复异步文件写入的同步等待问题
代码中使用File.WriteAllTextAsync(filePath, html)但未等待完成,直接启动ChromeDriver读取文件,可能导致文件未完全写入就被访问,引发后续加载或打印超时。可改为同步方法:File.WriteAllText(filePath, html);或修改方法为异步并添加等待:
// 方法签名改为async Task<byte[]> await File.WriteAllTextAsync(filePath, html);优化ChromeDriver初始化及超时配置
- 为ChromeDriver设置更长的命令超时时间,默认60秒可能不足以在流水线环境完成PDF渲染:
var driverService = ChromeDriverService.CreateDefaultService(); driverService.Start(); var driver = new ChromeDriver(driverService, driverOptions, TimeSpan.FromMinutes(5)); - 添加适配流水线环境的Chrome参数:
driverOptions.AddArgument("--no-sandbox"); driverOptions.AddArgument("--no-gpu"); driverOptions.AddArgument("--disable-dev-shm-usage"); // 解决共享内存不足问题 driverOptions.AddArgument("--disable-extensions"); driverOptions.AddArgument("--disable-plugins");
- 为ChromeDriver设置更长的命令超时时间,默认60秒可能不足以在流水线环境完成PDF渲染:
确保HTML页面完全加载后再执行打印
在调用ExecuteCdpCommand前,等待页面加载完成:new WebDriverWait(driver, TimeSpan.FromSeconds(30)).Until(d => ((IJavaScriptExecutor)d).ExecuteScript("return document.readyState").Equals("complete"));检查Azure DevOps流水线环境资源
- 确保流水线代理有足够的CPU和内存资源,PDF渲染对资源要求较高,资源不足会导致超时。
- 确认流水线中Chrome浏览器版本与ChromeDriver版本严格匹配,版本不一致可能引发兼容性问题。
简化PDF打印参数
先使用基础配置排查问题,排除复杂参数导致的渲染耗时:var printOptions = new Dictionary<string, object> { { "scale", 0.9 }, { "pageRanges", "1" }, { "preferCSSPageSize", false } };
内容的提问来源于stack exchange,提问作者Altafhusain Huddar

