Selenium
Selenium WebDriver 可以附加到应用程序已嵌入的浏览器上,驱动用户看到的页面。本教程介绍连接代码、ChromeDriver 的版本约束,以及哪些功能不可用。
Selenium 通过 ChromeDriver 访问 Chromium。ChromeDriver 通常会自行启动浏览器,但也可以连接到一个已经运行并通过 Chrome DevTools Protocol(即 CDP)公开远程调试端点的浏览器。Selenium 正是通过这种方式连接到 DotNetBrowser。
请先阅读 DevTools 协议,了解适用于所有自动化工具的通用规则。
前提条件
在运行测试场景的项目中引用以下两个 NuGet 包:
Selenium.WebDriver— WebDriver API。示例使用3.141.0,此处展示的 API 在 Selenium 4 中没有变化。Selenium.WebDriver.ChromeDriver— ChromeDriver 可执行文件。
DotNetBrowser 4.3.1 基于 Chromium 153.0.8010.37,因此请使用针对该版本构建的 Selenium.WebDriver.ChromeDriver 包。
启用端点
创建引擎并设置远程调试端口:
EngineOptions engineOptions = new EngineOptions.Builder
{
RemoteDebuggingPort = RemoteDebuggingPort
}
.Build();
engine = EngineFactory.Create(engineOptions);
browser = engine.CreateBrowser();
Dim engineOptionsBuilder As EngineOptions.Builder = new EngineOptions.Builder
With engineOptionsBuilder
.RemoteDebuggingPort = RemoteDebuggingPort
End With
Dim engineOptions = engineOptionsBuilder.Build()
engine = EngineFactory.Create(engineOptions)
browser = engine.CreateBrowser()
建立连接时只需要设置 RemoteDebuggingPort 这一项引擎选项。
连接驱动程序
将 ChromeOptions.DebuggerAddress 指向该端点,然后创建驱动程序:
ChromeOptions options = new ChromeOptions
{
DebuggerAddress = RemoteDebuggingAddress
};
IWebDriver webDriver = new ChromeDriver(options)
{
Url = StartPage
};
// 为 FindElement 留出等待页面加载的时间。
webDriver.Manage().Timeouts().ImplicitWait =
TimeSpan.FromSeconds(10);
Dim options As ChromeOptions = new ChromeOptions
With options
.DebuggerAddress = RemoteDebuggingAddress
End With
Dim webDriver As IWebDriver = new ChromeDriver(options)
With webDriver
.Url = StartPage
End With
' 为 FindElement 留出等待页面加载的时间。
webDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10)
DebuggerAddress 接收不包含协议方案的主机名和端口。该端口必须与引擎打开的端口一致:示例将 RemoteDebuggingPort 设置为 9222,因此驱动程序连接到 localhost:9222。设置 DebuggerAddress 后,ChromeDriver 会连接到该端点,而不是启动浏览器。
为 Url 赋值会导航 BrowserView 控件中已经打开的页面。示例将其指向随应用程序一起提供的页面,因此该场景不依赖任何外部网站。
连接后便可使用元素级 WebDriver API:FindElement、Click、SendKeys 以及脚本执行都会作用于嵌入式浏览器。隐式等待涵盖单击操作触发的导航,因此 FindElement 会不断重试,直至下一个页面加载完成,而不会在第一次尝试时失败。
窗口相关命令是个例外。该窗口属于您的应用程序,而不是 ChromeDriver:切换到全屏模式会直接失败,其他窗口命令也不可靠。请通过应用程序调整 BrowserView 控件的大小。
线程与生命周期
引擎启动后,示例会从窗体的 Load 处理程序中运行测试场景,并在场景结束时调用 webDriver.Quit()。
WebDriver 调用会阻塞线程,因此应在 UI 线程之外运行这些调用,并在操作控件之前将所有结果封送回 UI 线程。示例使用 Task.Run 封装测试场景,并在需要访问窗体时调用 Invoke。
故障排除
ChromeDriver 与 Chromium 版本不匹配是最常见的故障原因。ChromeDriver 会将其报告为会话创建错误,并在错误信息中列出这两个版本。请安装前提条件中指定的 Selenium.WebDriver.ChromeDriver 版本。
如果连接被拒绝,请检查创建引擎时是否设置了 RemoteDebuggingPort、DebuggerAddress 中的端口是否与其一致,以及驱动程序连接时引擎是否正在运行。也可以尝试使用 127.0.0.1 代替 localhost。