Selenium with C#
https://www.selenium.dev/documentation/webdriver/
Browser Navigation
Navigate to
跳转到
driver.Navigate().GoToUrl(@"https://selenium.dev")
Back
driver.Navigate().Back();
Forward
前进
driver.Navigate().Forward();
Refresh
刷新
driver.Navigate().Refresh();
Get Title
获取标题
driver.Title;
Windows and tabs
Get window handle
获取窗口句柄
driver.CurrentWindowHandle;
Switching windows
切换窗口
//Store the ID of the original window
string originalWindow = driver.CurrentWindowHandle;
//Check we don't have other windows open already
Assert.AreEqual(driver.WindowHandles.Count, 1);
//Click the link which opens in a new window
driver.FindElement(By.LinkText("new window")).Click();
//Wait for the new window or tab
wait.Until(wd => wd.WindowHandles.Count == 2);
//Loop through until we find a new window handle
foreach(string window in driver.WindowHandles)
{
if(originalWindow != window)
{
driver.SwitchTo().Window(window);
break;
}
}
//Wait for the new tab to finish loading content
wait.Until(wd => wd.Title == "Selenium documentation");
Closing a window
关闭窗口
//Close the tab or window
driver.Close();
//Switch back to the old tab or window
driver.SwitchTo().Window(originalWindow);
Quitting the browser
退出浏览器
driver.Quit();
Window management
窗口管理
Get window size
获取窗口尺寸
//Access each dimension individually
int width = driver.Manage().Window.Size.Width;
int height = driver.Manage().Window.Size.Height;
//Or store the dimensions and query them later
System.Drawing.Size size = driver.Manage().Window.Size;
int width1 = size.Width;
int height1 = size.Height;
Set window size
设置窗口尺寸
driver.Manage().Window.Size = new Size(1024, 768);
Get window position
获取窗口位置
//Access each dimension individually
int x = driver.Manage().Window.Position.X;
int y = driver.Manage().Window.Position.Y;
//Or store the dimensions and query them later
Point position = driver.Manage().Window.Position;
int x1 = position.X;
int y1 = position.Y;
Set window position
设置窗口位置
// Move the window to the top left of the primary monitor
driver.Manage().Window.Position = new Point(0, 0);
Maximize/Minimize window
最大化/最小化窗口
driver.Manage().Window.Maximize();
driver.Manage().Window.Minimize();
Fullscreen window
全屏
driver.Manage().Window.FullScreen();
TakeScreenshot
截屏
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
var driver = new ChromeDriver();
driver.Navigate().GoToUrl("http://www.example.com");
Screenshot screenshot = (driver as ITakesScreenshot).GetScreenshot();
screenshot.SaveAsFile("screenshot.png", ScreenshotImageFormat.Png); // Format values are Bmp, Gif, Jpeg, Png, Tiff
TakeElementScreenshot
元素截屏
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
// Webdriver
var driver = new ChromeDriver();
driver.Navigate().GoToUrl("http://www.example.com");
// Fetch element using FindElement
var webElement = driver.FindElement(By.CssSelector("h1"));
// Screenshot for the element
var elementScreenshot = (webElement as ITakesScreenshot).GetScreenshot();
elementScreenshot.SaveAsFile("screenshot_of_element.png");
Execute Script
执行Javascript语句
//creating Chromedriver instance
IWebDriver driver = new ChromeDriver();
//Creating the JavascriptExecutor interface object by Type casting
IJavaScriptExecutor js = (IJavaScriptExecutor) driver;
//Button Element
IWebElement button = driver.FindElement(By.Name("btnLogin"));
//Executing JavaScript to click on element
js.ExecuteScript("arguments[0].click();", button);
//Get return value from script
String text = (String)js.ExecuteScript("return arguments[0].innerText", button);
//Executing JavaScript directly
js.ExecuteScript("console.log('hello world')");
Locating elements
Locating one element
定位元素
使用 WebDriver 时要学习的最基本技术之一是如何在页面上查找元素。WebDriver 提供了许多内置的选择器类型,其中通过 ID 属性查找元素:
IWebElement element = driver.FindElement(By.Id("cheese"));
如示例所示,在 WebDriver 中定位元素是在WebDriver
实例对象上完成的 。该findElement(By)
方法返回另一个基本对象类型,WebElement
.
-
WebDriver
代表浏览器 -
WebElement
表示特定的 DOM 节点(控件,例如链接或输入字段等)
递进查找
IWebElement cheese = driver.FindElement(By.Id("cheese"));
IWebElement cheddar = cheese.FindElement(By.Id("cheddar"));
//CssSelector定位
driver.FindElement(By.CssSelector("#cheese #cheddar"));
查找元素集合
IReadOnlyList<IWebElement> muchoCheese = driver.FindElements(By.CssSelector("#cheese li"));
Element selection strategies
元素选择策略
Locator | Description |
---|---|
class name | Locates elements whose class name contains the search value (compound class names are not permitted) |
css selector | Locates elements matching a CSS selector |
id | Locates elements whose ID attribute matches the search value |
name | Locates elements whose NAME attribute matches the search value |
link text | Locates anchor elements whose visible text matches the search value |
partial link text | Locates anchor elements whose visible text contains the search value. If multiple elements are matching, only the first one will be selected. |
tag name | Locates elements whose tag name matches the search value |
xpath | Locates elements matching an XPath expression |
使用选择器的技巧
通常,如果 HTML ID 可用、唯一且一致可预测,则它们是在页面上定位元素的首选方法。它们往往工作得非常快,并且放弃了复杂的 DOM 遍历带来的大量处理。
如果唯一 ID 不可用,则编写良好的 CSS 选择器是定位元素的首选方法。XPath 与 CSS 选择器一样有效,但语法复杂且经常难以调试。尽管 XPath 选择器非常灵活,但它们通常没有经过浏览器供应商的性能测试,而且往往很慢。
基于linkText和partialLinkText 的选择策略的缺点在于它们仅适用于链接元素。此外,它们在 WebDriver 内部调用 XPath 选择器。
标签名称可能是一种危险的定位元素的方式。页面上经常会出现多个相同标签的元素。这在调用返回元素集合的findElements(By)方法时非常有用。
建议是使您的定位器尽可能紧凑和可读。要求 WebDriver 遍历 DOM 结构是一项代价高昂的操作,您可以缩小搜索范围越多越好。
相对定位器
Selenium 4 特性
using static OpenQA.Selenium.RelativeBy;
IWebElement passwordField = driver.FindElement(By.Id("password"));
IWebElement emailAddressField = driver.FindElement(WithTagName("input").Above(passwordField));
using static OpenQA.Selenium.RelativeBy;
IWebElement submitButton = driver.FindElement(By.Id("submit"));
IWebElement cancelButton = driver.FindElement(WithTagName("button").LeftOf(submitButton));
using static OpenQA.Selenium.RelativeBy;
IWebElement emailAddressLabel = driver.FindElement(By.Id("lbl-email"));
IWebElement emailAddressField = driver.FindElement(WithTagName("input").Near(emailAddressLabel));
Waits
Explicit wait
显示等待
driver = new ChromeDriver();
driver.Url = "https://www.google.com/ncr";
driver.FindElement(By.Name("q")).SendKeys("cheese" + Keys.Enter);
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement firstResult = wait.Until(e => e.FindElement(By.XPath("//a/h3")));
Console.WriteLine(firstResult.Text);
匿名函数优化
using (var driver = new FirefoxDriver())
{
var foo = new WebDriverWait(driver, TimeSpan.FromSeconds(3))
.Until(drv => drv.FindElement(By.Name("q")));
Debug.Assert(foo.Text.Equals("Hello from JavaScript!"));
}
预期条件
元素可点击
new WebDriverWait(driver, TimeSpan.FromSeconds(3)).Until(ExpectedConditions.ElementToBeClickable(By.XPath("//a/h3")));
Implicit wait
隐式等待
通过隐式等待,WebDriver 在尝试查找任何元素时会在一段时间内轮询 DOM 。
警告: 不要混合隐式和显式等待。这样做可能会导致不可预测的等待时间。
IWebDriver driver = new ChromeDriver();
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
driver.Url = "http://somedomain/url_that_delays_loading";
IWebElement dynamicElement = driver.FindElement(By.Name("dynamicElement"));
FluentWait
流利等待
FluentWait 实例定义了等待条件的最长时间,以及检查条件的频率
用户可以将等待配置为在等待时忽略特定类型的异常,例如NoSuchElementException
在页面上搜索元素时。
using (var driver = new FirefoxDriver())
{
WebDriverWait wait = new WebDriverWait(driver, timeout: TimeSpan.FromSeconds(30))
{
PollingInterval = TimeSpan.FromSeconds(5),
};
wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
var foo = wait.Until(drv => drv.FindElement(By.Id("foo")));
}
JavaScript alerts, prompts and confirmations
Alerts
//Click the link to activate the alert
driver.FindElement(By.LinkText("See an example alert")).Click();
//Wait for the alert to be displayed and store it in a variable
IAlert alert = wait.Until(ExpectedConditions.AlertIsPresent());
//Store the alert text in a variable
string text = alert.Text;
//Press the OK button
alert.Accept();
Confirm
//Click the link to activate the alert
driver.FindElement(By.LinkText("See a sample confirm")).Click();
//Wait for the alert to be displayed
wait.Until(ExpectedConditions.AlertIsPresent());
//Store the alert in a variable
IAlert alert = driver.SwitchTo().Alert();
//Store the alert in a variable for reuse
string text = alert.Text;
//Press the Cancel button
alert.Dismiss();
Prompt
提示
//Click the link to activate the alert
driver.FindElement(By.LinkText("See a sample prompt")).Click();
//Wait for the alert to be displayed and store it in a variable
IAlert alert = wait.Until(ExpectedConditions.AlertIsPresent());
//Type your message
alert.SendKeys("Selenium");
//Press the OK button
alert.Accept();
Http proxies
代理服务器充当客户端和服务器之间请求的中介。简而言之,流量通过代理服务器流向您请求的地址并返回。
带有 Selenium 的自动化脚本代理服务器可能有助于:
-
捕获网络流量
-
模拟网站进行的后端调用
-
在复杂的网络拓扑或严格的公司限制/政策下访问所需的网站。
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
public class ProxyTest{
public 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/");
}
}
Page loading strategy
normal
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace pageLoadStrategy {
class pageLoadStrategy {
public static void Main(string[] args) {
var chromeOptions = new ChromeOptions();
chromeOptions.PageLoadStrategy = PageLoadStrategy.Normal;
IWebDriver driver = new ChromeDriver(chromeOptions);
try {
driver.Navigate().GoToUrl("https://example.com");
} finally {
driver.Quit();
}
}
}
}
eager
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace pageLoadStrategy {
class pageLoadStrategy {
public static void Main(string[] args) {
var chromeOptions = new ChromeOptions();
chromeOptions.PageLoadStrategy = PageLoadStrategy.Eager;
IWebDriver driver = new ChromeDriver(chromeOptions);
try {
driver.Navigate().GoToUrl("https://example.com");
} finally {
driver.Quit();
}
}
}
}
none
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace pageLoadStrategy {
class pageLoadStrategy {
public static void Main(string[] args) {
var chromeOptions = new ChromeOptions();
chromeOptions.PageLoadStrategy = PageLoadStrategy.None;
IWebDriver driver = new ChromeDriver(chromeOptions);
try {
driver.Navigate().GoToUrl("https://example.com");
} finally {
driver.Quit();
}
}
}
}
Web element
Find Element
// Get search box element from webElement 'q' using Find Element
IWebElement searchbox = driver.FindElement(By.Name("q"));
Find Elements
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using System.Collections.Generic;
namespace FindElementsExample {
class FindElementsExample {
public static void Main(string[] args) {
IWebDriver driver = new FirefoxDriver();
try {
// Navigate to Url
driver.Navigate().GoToUrl("https://example.com");
// Get all the elements available with tag name 'p'
IList < IWebElement > elements = driver.FindElements(By.TagName("p"));
foreach(IWebElement e in elements) {
System.Console.WriteLine(e.Text);
}
} finally {
driver.Quit();
}
}
}
}
Find Element From Element
IWebElement searchForm = driver.FindElement(By.TagName("form"));
IWebElement searchbox = searchForm.FindElement(By.Name("q"));
Find Elements From Element
// Get element with tag name 'div'
IWebElement element = driver.FindElement(By.TagName("div"));
// Get all the elements available with tag name 'p'
IList < IWebElement > elements = element.FindElements(By.TagName("p"));
foreach(IWebElement e in elements) {
System.Console.WriteLine(e.Text);
}
Get Active Element
它用于跟踪(或)查找在当前浏览上下文中具有焦点的 DOM 元素。
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace ActiveElement {
class ActiveElement {
public static void Main(string[] args) {
IWebDriver driver = new ChromeDriver();
try {
// Navigate to Url
driver.Navigate().GoToUrl("https://www.google.com");
driver.FindElement(By.CssSelector("[name='q']")).SendKeys("webElement");
// Get attribute of current active element
string attr = driver.SwitchTo().ActiveElement().GetAttribute("title");
System.Console.WriteLine(attr);
} finally {
driver.Quit();
}
}
}
}
Is Element Enabled
// Store the WebElement
IWebElement element = driver.FindElement(By.Name("btnK"));
// Prints true if element is enabled else returns false
System.Console.WriteLine(element.Enabled);
Get Element Rect
获取元素矩形
driver.Navigate().GoToUrl("https://example.com");
var res = driver.FindElement(By.CssSelector("h1"));
// Return x and y coordinates referenced element
System.Console.WriteLine(res.Location);
// Returns height, width
System.Console.WriteLine(res.Size);
Get Element CSS Value
获取元素 CSS 值
// Navigate to Url
driver.Navigate().GoToUrl("https://www.example.com");
// Retrieves the computed style property 'color' of linktext
String cssValue = driver.FindElement(By.LinkText("More information...")).GetCssValue("color");
Get Element Text
// Navigate to url
driver.Url="https://example.com";
// Retrieves the text of the element
String text = driver.FindElement(By.CssSelector("h1")).Text;
Keyboard
键盘代表一个键盘事件。KeyBoard 操作是通过使用低级接口执行的,这允许我们向 Web 浏览器提供虚拟化设备输入。
sendKeys
// Enter "webdriver" text and perform "ENTER" keyboard action
driver.FindElement(By.Name("q")).SendKeys("webdriver" + Keys.Enter);
keyDown
keyDown 用于模拟按下修饰键(CONTROL、SHIFT、ALT)的动作
// Perform action ctrl + A (modifier CONTROL + Alphabet A) to select the page
Actions actionProvider = new Actions(driver);
IAction keydown = actionProvider.KeyDown(Keys.Control).SendKeys("a").Build();
keydown.Perform();
keyUp
keyUp 用于模拟修饰键(CONTROL、SHIFT、ALT)的上键(或)键释放动作
// Enters text "qwerty" with keyDown SHIFT key and after keyUp SHIFT key (QWERTYqwerty)
action.KeyDown(Keys.Shift).SendKeys(search, "qwerty").KeyUp(Keys.Shift).SendKeys("qwerty").Perform();