自动化测试如此容易!多语言自动化测试框架 Selenium 编程(C#篇)
介绍
Selenium 官网:https://www.selenium.dev/
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
更改为 eager
或 none
以加快会话加载速度。
设置方法:
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=file
的 input
标签中,填写本地路径的文件地址,这个地址需要填写文件的绝对路径。
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 的教程就到这里,读者可到官方文档了解更多。
自动化测试如此容易!多语言自动化测试框架 Selenium 编程(C#篇)的更多相关文章
- Android 框架式编程 —— 起篇
一般的,在开发的时候,写过的代码在需求变更后,发现需要改动非常多的地方,那么说明之前的代码的架构肯定是存在问题的. 下面我们结合面向对象的六大基本原则谈Android 框架式编程.首先先介绍一下面向对 ...
- RobotFramework自动化测试框架-Selenium Web自动化(二)关于在RobotFramework中如何使用Selenium很全的总结(上)
好久没有继续分享关于自动化测试相关的东西了,自动化在现今的测试领域已经越来越重要了,大部分公司在测试岗位招聘中都需要会相关的自动化测试知识.而 RobotFramework自动化测试框架 是自动化测试 ...
- RobotFramework自动化测试框架-Selenium Web自动化(三)关于在RobotFramework中如何使用Selenium很全的总结(下)
本文紧接着RobotFramework自动化测试框架-Selenium Web自动化(二)关于在RobotFramework中如何使用Selenium很全的总结(上)继续分享RobotFramewor ...
- 《Selenium 2自动化测试实战 基于Python语言》中发送最新邮件无内容问题的解决方法
虫师的<Selenium 2自动化测试实战 基于Python语言>是我自动化测试的启蒙书 也是我推荐的自动化测试入门必备书,但是书中有一处明显的错误,会误导很多读者,这处错误就是第8章自动 ...
- 小白学 Python 爬虫(28):自动化测试框架 Selenium 从入门到放弃(下)
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 《Selenium2自动化测试实战--基于Python语言》 --即将面市
发展历程: <selenium_webdriver(python)第一版> 将本博客中的这个系列整理为pdf文档,免费. <selenium_webdriver(python)第 ...
- 关于《Selenium3自动化测试实战--基于python语言》
2016年1月,机缘巧合下我出版了<Selenium2自动化测试实战--基于python语言>这本书,当时写书的原因是,大部分讲Selenium的书并不讲编程语言和单元测试框,如果想在项目 ...
- selenium2自动化测试实战--基于Python语言
自动化测试基础 一. 软件测试分类 1.1 根据项目流程阶段划分软件测试 1.1.1 单元测试 单元测试(或模块测试)是对程序中的单个子程序或具有独立功能的代码段进行测试的过程. 1.1.2 集成测试 ...
- 移动端自动化测试(一)之 Appium+Pyhton环境准备篇
移动端自动化测试(一)之 Appium+Pyhton环境准备篇 2016-11-17 16:51 by CockRoacher, 5046 阅读, 1 评论, 收藏, 编辑 由于工作的需要进行Andr ...
- 手机自动化测试:搭建appium手机自动化测试开发环境
手机自动化测试:搭建appium手机自动化测试开发环境 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大 ...
随机推荐
- 【Serverless】Unity快速集成认证服务实现邮件登录
概述: 认证服务可以为您的应用快速构建安全可靠的用户认证系统,您只需在应用中访问认证服务的相关能力,而不需要关心云侧的设施和实现. 本次将带来如何使用Unity编辑器快速集成认证服务SDK并实现邮箱 ...
- 实践案例:平安健康的 Dubbo3 迁移历程总结
本篇是 Apache Dubbo 的实践案例.感兴趣的朋友可以访问官网了解更多详情,或搜索关注官方微信公众号 Apache Dubbo 跟进最新动态. 1 背景 我们公司从15年开始就使⽤dubbo作 ...
- C++编程笔记(通信)(win32平台)
目录 一.初始化网络库 二.socket套接字 2.1服务端 2.2客户端 三.发送.接收数据 3.1发送 3.2接收数据 四.自定义的结构体 4.1 发送端 4.2接收端 IPV6版本套接字的创建 ...
- python3 利用当前时间、随机数产生一个唯一的数字作为文件名
一.python3 利用当前时间.随机数产生一个唯一的数字作为文件名 代码如下: #-*-coding:utf-8-*- #python3自动生成文件名 from datetime import * ...
- 使用 Visual Studio 2022 调试Dapr 应用程序
使用Dapr 编写的是一个多进程的程序,使用Visual Studio 调试起来可能会比较困难,因为 Visual Studio 默认只会把你当前设置的启动项目的启动调试. 好在有Visual Stu ...
- 使用linux的ffmpeg进行B站直播推流
很久之前买了个友善的开发板R2S,一直在家吃灰.最近看到网上有用ffmpeg进行直播推流的案例,想把吃灰的的开发板利用起来,于是有了这篇教程. 第一步:安装ffmpeg sudo apt update ...
- 【转载】SQL SERVER 通过对汉字、字母和数字的Unicode码区间的判断来识别字符串
A~Z :65~90 a~z :97~122 0-9 : 48-57 –汉字unicode编码范围:[0x4e00,0x9fa5](或十进制[19968,40869]) SELECT * FR ...
- 使用“宝塔一键迁移”工具,将typecho博客迁移到京东云cvm云主机
作者:京东科技 林中 服务器更换.网站搬家,对于很多开发者新手来说不是一件容易的事情,需要迁移网站程序.数据库,修改数据库连接文件等.在云迁移方案中,宝塔是非常简单好用的服务器运维面板,能够极大提升运 ...
- 反馈电路的Bode分析法
1 前言 在反馈电路的分析中,如果前向放大倍数为Aopen,反馈系数为β,则闭环传递函数Aclose=Aopen/(1+Aopenβ),其中Aopenβ为环路增益.但是,在Aopen和β的计算中均要考 ...
- 洛谷 P2440木材加工 题解
这是一道二分答案算法题,洛谷标签中的贪心等完全用不到. 这道题的数据范围较大,所以保险起见,整型的数据我们都开成longlong 题意很好理解,这里就不做过多的分析了,直接看代码,后面有注释: #in ...