自动化测试如此容易!多语言自动化测试框架 Selenium 编程(C#篇)

简介: 自动化测试如此容易!多语言自动化测试框架 Selenium 编程(C#篇)

Selenium 是功能强大的自动化测试工具集,是支持 Web 浏览器自动化的一系列工具和库的总括项目,一共包括以下三个项目:

  • Selenium WebDriver
  • Selenium IDE
  • Selenium Grid

Selenium 的核心是 WebDriver,可以在许多浏览器中交换运行,WebDriver 以原生的方式驱动浏览器,。

WebDriver 架构设计如下:

对每种浏览器编写一个 Driver,如 ChromeDriver,这是操作浏览器的驱动,对外提供了各类操作接口。Selenium 设计了 WebDriver 抽象,以便通过统一的抽象使用各类浏览器驱动。

或者还可以远程访问接口:

下面笔者介绍在 C# 中如何使用 Selenium WebDriver 编写自动化测试程序。

安装依赖

创建一个 C# 控制台项目,首先安装依赖包 Selenium.WebDriver,这个库提供了浏览器驱动接口的基础 API 和统一抽象。

Selenium.WebDriver

接着,安装浏览器对应的驱动实现:

Selenium.WebDriver.ChromeDriver

只要搜索 Selenium.WebDriver 即可,然后根据浏览器补充后缀,下载对应的浏览器驱动。

第一个 demo

打开:https://www.selenium.dev/selenium/web/web-form.html

这个地址是官方用于测试的页面,里面有比较多的 html 组件,足够我们学习使用。

下面这个示例中,包括了打开页面、查找元素、填充内容和获取信息的代码,读者可以运行这段代码从中了解编写自动化测试程序的基本执行流程,更多的细节将在后面的小节中讲解。

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
class Program
{
  static void Main()
  {
        // 使用 ChromeDriver 驱动
    IWebDriver driver = new ChromeDriver();
    // 启动的时候打开这个页面
    driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/web-form.html");
    // 获取页面信息
    var title = driver.Title;
    // 隐式等待,页面元素不会立马出现,需要单独一段时间
    driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(500);
    // 搜索元素
    var textBox = driver.FindElement(By.Name("my-text"));
    var submitButton = driver.FindElement(By.TagName("button"));
    // 往输入框填充文本
    textBox.SendKeys("Selenium");
    // 点击提交按钮
    submitButton.Click();
    // 点击提交按钮之后,页面会刷新,此时获取的是跳转之后的页面的元素
    var message = driver.FindElement(By.Id("message"));
    var value = message.Text;
    // 退出
    driver.Quit();
  }
}

注意:demo 程序启动时,会启动 Chrome 浏览器,如果启动浏览器太慢,demo 程序会报错退出。

因此需要先启动 Chrome 浏览器,再启动 demo 程序,以便减少 Chrome 浏览器新窗口的启动时间。

demo 程序启动后,会自动填充表单和提交,接着跳转到新的页面。

页面加载策略

页面开发模式有多种多样,如 PHP、asp 这种一体式开发,如服务器渲染然后返回整个页面、前后端分离先加载静态资源然后从后端 API 中加载数据生成页面。

很多时候,页面不会短时间完成渲染,有些页面元素需要一段时间后才能出现。在使用 WebDriver 的时候,我们也可以根据需求决定在什么时候启动自动化操作。

页面有三种基本加载策略:

策略 就绪状态 备注
normal complete 默认值,,等待所有资源下载
eager interactive DOM 访问已准备就绪, 但诸如图像的其他资源可能仍在加载。
none Any 完全不会阻塞 WebDriver,WebDriver 仅等待初始页面已下载。

如果由于下载对自动化不重要的资源(例如, 图像、css、js) 而需要很长时间才能加载页面,,可以将默认参数 normal 更改为 eagernone 以加快会话加载速度。

设置方法:

var chromeOptions = new ChromeOptions();
chromeOptions.PageLoadStrategy = PageLoadStrategy.Normal;
IWebDriver driver = new ChromeDriver(chromeOptions);

另外,WebDriver 提供了三种方式等待页面元素的出现:

  • 显式等待
  • 隐式等待
  • 流畅等待

我们可以使用等待来让 findElement 调用等待直到脚本中动态添加的元素被添加到DOM中:

WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement firstResult = wait.Until(e => e.FindElement(By.XPath("//a/h3")));

这种方法称为显式等待

WebDriver 会等待路径 //a/h3 的元素出现,最大等待时间为 10s。

而通过隐式等待,WebDriver 在试图查找_任何_元素时在一定时间内轮询DOM。当网页上的某些元素不是立即可用并且需要一些时间来加载时是很有用的。

隐式等待是告诉 WebDriver 如果在查找一个或多个不是立即可用的元素时轮询 DOM 一段时间。一旦设置好,隐式等待就被设置为会话的生命周期。

设置隐式等待的轮询时间:

driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(500);

警告: 不要混合使用隐式和显式等待。这样做会导致不可预测的等待时间。例如,将隐式等待设置为10秒,将显式等待设置为15秒,可能会导致在20秒后发生超时。

流畅等待 定义了等待条件的最大时间量,以及检查条件的频率。

用户可以配置等待来忽略等待时出现的特定类型的异常,例如在页面上搜索元素时出现的NoSuchElementException

WebDriverWait wait = new WebDriverWait(driver, timeout: TimeSpan.FromSeconds(30))
{
  PollingInterval = TimeSpan.FromSeconds(5),
};

代理

代理服务器充当客户端和服务器之间的请求中介,使用代理服务器用于 Selenium 的自动化脚本, 可能对以下方面有益:

  • 捕获网络流量
  • 模拟网站后端响应
  • 在复杂的网络拓扑结构或严格的公司限制/政策下访问目标站点.

如果在公司环境中,或者需要开启飞机上网,浏览器无法连接到 URL,则需要借助代理进行访问。

Selenium WebDriver 提供了如下设置代理的方法,代码示例如下:

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
class Program
{
  static void Main()
  {       
    ChromeOptions options = new ChromeOptions();
    Proxy proxy = new Proxy();
    proxy.Kind = ProxyKind.Manual;
    proxy.IsAutoDetect = false;
    proxy.SslProxy = "<HOST:PORT>";
    options.Proxy = proxy;
    options.AddArgument("ignore-certificate-errors");
    IWebDriver driver = new ChromeDriver(options);
    driver.Navigate().GoToUrl("https://www.selenium.dev/");
  }
}

浏览器版本

例如, 假设想使用 Chrome 版本 67 在 Windows XP 上运行 Chrome:

var chromeOptions = new ChromeOptions();
chromeOptions.BrowserVersion = "67";
chromeOptions.PlatformName = "Windows XP";

元素操作

元素操作主要分为下面这几种:

  • 文件上传
  • 查询网络元素:根据提供的定位值定位元素
  • Web元素交互:用于操纵表单的高级指令集
  • 定位策略:在 DOM中 标识一个或多个特定元素的方法
  • 元素的信息:html 元素的属性

下面来介绍不同 html 元素的操作方法示例。

文件上传

上传文件实际上是在 type=fileinput 标签中,填写本地路径的文件地址,这个地址需要填写文件的绝对路径。

using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace SeleniumDocumentation.SeleniumPRs
{
  class FileUploadExample
  {
    static void Main(String[] args)
    {
      IWebDriver driver = new ChromeDriver();
      try
      {
        // Navigate to Url
        driver.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/web-form.html");
        // 文件路径一定是可以存在的,不能乱填,建议绝对路径
        driver.FindElement(By.Name("my-file")).SendKeys("D:/Desktop/images/学习.jpg");
        var submitButton = driver.FindElement(By.TagName("button"));
        submitButton.Click();
        if (driver.PageSource.Contains("File Uploaded!"))
        {
          Console.WriteLine("file uploaded");
        }
        else
        {
          Console.WriteLine("file not uploaded");
        }
        driver.Quit();
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex);
      }
    }
  }
}

查找元素

在 WebDriver 中有 8 种不同的内置元素定位策略:

定位器 Locator 描述
class name 定位class属性与搜索值匹配的元素(不允许使用复合类名)
css selector 定位 CSS 选择器匹配的元素
id 定位 id 属性与搜索值匹配的元素
name 定位 name 属性与搜索值匹配的元素
link text 定位link text可视文本与搜索值完全匹配的锚元素
partial link text 定位link text可视文本部分与搜索值部分匹配的锚点元素。如果匹配多个元素,则只选择第一个元素。
tag name 定位标签名称与搜索值匹配的元素
xpath 定位与 XPath 表达式匹配的元素

下面是查找元素的用例:

// 通过 id 或 name
IWebElement vegetable = driver.FindElement(By.ClassName("tomatoes"));
IWebElement fruits = driver.FindElement(By.Id("fruits"));
IWebElement fruit = fruits.FindElement(By.ClassName("tomatoes"));
// 通过 css 选择器
var fruit = driver.FindElement(By.CssSelector("#fruits .tomatoes"));
// 返回多个元素
IReadOnlyList<IWebElement> plants = driver.FindElements(By.TagName("li"));

获取当前页面的焦点在哪个元素:

var element = driver.SwitchTo().ActiveElement();
string attr = element.GetAttribute("title");

页面元素交互

仅有五种基本命令可用于元素的操作:

  • 点击 (适用于任何元素)
  • 发送键位 (仅适用于文本字段和内容可编辑元素,.SendKeys())
  • 清除 (仅适用于文本字段和内容可编辑元素)
  • 提交 (仅适用于表单元素)(在Selenium 4中不再建议使用)
  • 选择(查找元素)
点击

可以触发元素的点击事件:

var submitButton = driver.FindElement(By.TagName("button"));
submitButton.Click();
输入

元素发送键位命令,即 .SendKeys() ,这个方法对可编辑的元素都通用,如 input、select 等元素。

driver.FindElement(By.Name("my-file")).SendKeys("D:/Desktop/images/学习.jpg");
清除

对于可编辑文本或具有输入的元素,如文本域、选择框、文件上传框的,可以清除元素当前的value 属性。

IWebElement searchInput = driver.FindElement(By.Name("q"));
searchInput.SendKeys("selenium");
// Clears the entered text
searchInput.Clear();

获取元素属性

  • 是否显示
  • 是否启用
  • 是否被选定
  • 获取元素标签名
  • 位置和大小
  • 获取元素CSS值
  • 文本内容
  • 获取特性或属性

在 JS 中,我们可以这样获取一个元素的值或其它属性:

document.getElementById("my-text-id").value
"111111111"

在 WebDriver 中可以通过 IWebElement 接口的 字段/属性 获取元素属性,但不多:

Boolean is_email_visible = driver.FindElement(By.Name("email_input")).Displayed;

其它需要的属性可以通过 GetAttribute 等方法获取,如:

string attr = element.GetAttribute("title");

IWebElement 的定义如下:

public interface IWebElement : ISearchContext
  {
    string TagName { get; }
    string Text { get; }
    bool Enabled { get; }
    bool Selected { get; }
    Point Location { get; }
    Size Size { get; }
    bool Displayed { get; }
    void Clear();
    void SendKeys(string text);
    void Submit();
    void Click();
    string GetAttribute(string attributeName);
    string GetDomAttribute(string attributeName);
    string GetDomProperty(string propertyName);
    string GetCssValue(string propertyName);
    ISearchContext GetShadowRoot();
  }

浏览器页面

对于浏览器页面的操作,无外乎下面四种:

  • 打开网站
  • 后退
  • 前进
  • 刷新

示例代码也很简单:

// 打开
driver.Navigate().GoToUrl(@"https://selenium.dev");
// 后退
driver.Navigate().Back();
// 前进
driver.Navigate().Forward();
// 刷新
driver.Navigate().Refresh();

用户登录凭证

目前只发现了使用 Basic、Cookie 两种登录认证方式, JWT Token 这种需要设置 Header 头的方式找不到实现。

下面是使用 Cookie 打开网页的示例:

var chromeOptions = new ChromeOptions();
      IWebDriver driver = new ChromeDriver(chromeOptions);
      try
      {
        driver.Navigate().GoToUrl("https://www.google.com");
        // Adds the cookie into current browser context
        driver.Manage().Cookies.AddCookie(new Cookie("key", "value"));
        driver.FindElement(By.CssSelector("[name='q']")).SendKeys("webElement");
        // Get attribute of current active element
        var btnK = driver.FindElement(By.Name("btnK"));
        btnK.Click();
      }
      finally
      {
        driver.Quit();
      }

关于使用 C# 开发 Selenium WebDriver 的教程就到这里,读者可到官方文档了解更多。

相关文章
|
8月前
|
前端开发 测试技术 API
测试金字塔:别再只盯着UI自动化了
测试金字塔:别再只盯着UI自动化了
738 116
|
8月前
|
敏捷开发 测试技术 API
测试金字塔:构建高效自动化测试策略的基石
测试金字塔:构建高效自动化测试策略的基石
626 116
|
8月前
|
设计模式 前端开发 测试技术
告别脆弱:构建稳定UI自动化测试的3个核心策略
告别脆弱:构建稳定UI自动化测试的3个核心策略
802 113
|
8月前
|
人工智能 自然语言处理 测试技术
从人工到AI驱动:天猫测试全流程自动化变革实践
天猫技术质量团队探索AI在测试全流程的落地应用,覆盖需求解析、用例生成、数据构造、执行验证等核心环节。通过AI+自然语言驱动,实现测试自动化、可溯化与可管理化,在用例生成、数据构造和执行校验中显著提效,推动测试体系从人工迈向AI全流程自动化,提升效率40%以上,用例覆盖超70%,并构建行业级知识资产沉淀平台。
从人工到AI驱动:天猫测试全流程自动化变革实践
|
8月前
|
人工智能 自然语言处理 JavaScript
利用MCP Server革新软件测试:更智能、更高效的自动化
MCP Server革新软件测试:通过标准化协议让AI实时感知页面结构,实现自然语言驱动、自适应维护的自动化测试,大幅提升效率,降低脚本开发与维护成本,推动测试左移与持续测试落地。
|
9月前
|
存储 关系型数据库 测试技术
玩转n8n测试自动化:核心节点详解与测试实战指南
n8n中节点是自动化测试的核心,涵盖触发器、数据操作、逻辑控制和工具节点。通过组合节点,测试工程师可构建高效、智能的测试流程,提升测试自动化能力。
|
8月前
|
测试技术 API 数据库
测试金字塔:构建高效自动化测试策略的基石
测试金字塔:构建高效自动化测试策略的基石
645 114
|
9月前
|
机器学习/深度学习 人工智能 测试技术
EdgeMark:嵌入式人工智能工具的自动化与基准测试系统——论文阅读
EdgeMark是一个面向嵌入式AI的自动化部署与基准测试系统,支持TensorFlow Lite Micro、Edge Impulse等主流工具,通过模块化架构实现模型生成、优化、转换与部署全流程自动化,并提供跨平台性能对比,助力开发者在资源受限设备上高效选择与部署AI模型。
786 9
EdgeMark:嵌入式人工智能工具的自动化与基准测试系统——论文阅读
|
9月前
|
自然语言处理 前端开发 测试技术
使用 Playwright MCP 实现 UI 自动化测试
本文介绍如何结合Playwright与MCP协议实现智能化UI自动化测试。通过自然语言指令控制浏览器,降低技术门槛,提升效率,并涵盖环境搭建、核心功能、实战案例及最佳实践,展现对话式自动化的未来趋势。

热门文章

最新文章