目录

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 包。

启用端点 

创建引擎并设置远程调试端口:

C#
VB

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 指向该端点,然后创建驱动程序:

C#
VB

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。

完整示例可在我们的代码仓库中获取: C#, VB.NET。