click()
触发当前元素点击事件
clear()
清空内容
sendKeys()
向文本框一类的元素中写入内容
按键操作
-
ctrl + a 全选
element.sendKeys(Keys.CONTROL,"a")
-
ctrl + x 剪切
element.sendKeys(Keys.CONTROL,"x")
-
ctrl + c 复制
element.sendKeys(Keys.CONTROL,"c")
-
ctrl + v 粘贴
element.sendKeys(Keys.CONTROL,"v")
-
回车
element.sendKeys(Keys.ENTER)
-
删除
element.sendKeys(Keys.BACK_SPACE)
-
空格
element.sendKeys(Keys.SPACE)
常用元素操作
-
getTagName()
获取元素的标签名
-
getAttribute(属性名)
根据属性名获取元素属性值
-
getText()
获取当前元素的文本值
-
isDisplayed()
查看元素是否显示
WebDriver常用 API
-
get(String url)
访问指定url页面
-
getCurrentUrl()
获取当前页面的url地址
-
getTitle()
获取当前页面的标题
-
getPageSource()
获取当前页面的源代码
-
quit()
关闭驱动对象以及所有相关的窗口
-
close()
关闭当前窗口
-
getWindowHandle()
返回当前页面句柄
-
getWindowHandles()
返回所有由驱动对象打开页面的所有句柄,页面不同,句柄也不一样
-
manage()
此方法可以获取 Options --- 浏览器菜单操作对象
// 获取 Option 对象操作浏览器 Options options = driver.manage(); // 设置窗口全屏显示 options.window().fullscreen(); // 设置窗口最大化 options.window().maximize(); // 获取窗口的宽高 Dimension size = options.window().getSize(); System.out.println("窗口高: " + size.getHeight() + ", 窗口宽:" + size.getWidth()); // 获取窗口的坐标 Point position = options.window().getPosition(); System.out.println("X: " + position.getX() + ", Y: " + position.getY());
-
navigate对象
// 获取 navigate 对象 Navigation navigate = driver.navigate(); // 访问指定的 url navigate.to("http://www.bing.com"); // 刷新页面 navigate.refresh(); // 浏览器后退 navigate.back(); // 浏览器前进 navigate.forward();
三大等待范式
硬性等待
-
实现原理
线程休眠,强制等待
Thread.sleep(long milis);
硬性等待一般用在获取 Driver 实例以后
public class Drivers { public static ChromeDriver getChromeDriver() { System.setProperty("webdriver.chrome.driver", "src/test/resources/chromedriver.exe"); ChromeDriver chromeDriver = new ChromeDriver(); return chromeDriver; } } public static void main(String[] args) throws InterruptedException { ChromeDriver driver = Drivers.getChromeDriver(); driver.get("http://www.bing.com") driver.findElement(By.id("kw")).sendKeys("腾讯课堂"); driver.findElement(By.id("su")).click(); // 这里往往可能因为代码执行太快,导致 UI 元素还没有显示出来代码已经执行到了,从而报找不到元素的错误,所以此时可以通过强制等待让线程休眠 等待页面元素加载完成再执行后续代码 Thread.sleep(3000) driver.findElement(By.xpath("//a[text='官网']")).click(); }
隐式等待
-
实现原理
再设置的超时范围内不断查找元素,直到找到元素或者超时
-
设置方式
driver.manage().timeouts().implicitlyWait(long time, TimeUnit unit);
优点:相对灵活 缺点:设置是针对全局的, 在 WebDriver 实例整个生命周期有效,但并不是所有元素都需要等待。
ChromeDriver driver = Drivers.getChromeDriver();
// 隐式等待
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
driver.get("http://www.jd.com");
WebElement input = driver.findElement(By.id("key"));
input.sendKeys("小米");
input.sendKeys(Keys.ENTER)
显示等待
-
用来等待某个条件发生后再继续执行后续代码(如找到元素、元素可点击、元素已显示等待)
-
设置方式:
WebDriverWait wait = new WebDriverWait(WebDriver driver, long time);
WebDriverElement element = wait.until(exceptionCondition);
-
常用方法:
-
visibilityOfElementLocated(By locator)
页面元素在页面存在并且可见
-
elementToBeClickable(By locator)
页面元素是否在页面上可用和可被点击
-
elementToBeSelected(WebElement element)
页面元素处于被选中状态
-
textToBePresentInElement(By locator)
在页面元素中是否包含特定的文本
-
presenceOfElementLocated(By locator)
页面元素在页面中存在
-
-
代码实例:
ChromeDriver driver = Drivers.getChromeDriver(); driver.get("http://www.jd.com"); WebElement input = driver.findElement(By.id("key")); input.sendKeys("小米11"); input.sendKeys(Keys.ENTER); // 显示等待 5s WebDriverWait wait = new WebDriverWait(driver, 5); WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//a[text()='小米京东自营旗舰店']"))); element.click();
WebDriver中可以设置多种类型的超时时间
-
implicitlyWait
识别对象时的超时时间。过了这个时间如果对象还没有找到的话,就会抛出 NoSuchElement异常
-
setScriptTimeout
设置异步脚本的超时时间。WebDriver可以异步执行脚本,这个是设置异步脚本执行时,脚本返回结果的超时时间。
-
pageLoadTimeout
页面加载时的超时时间。因为 WebDriver 会等页面加载完毕再进行后面的操作。所以如果页面在这个超时时间内没有加载完成,那么 WebDriver 就会抛出异常。
-
代码实例
// 设置元素定位时间为5秒
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
// 设置异步脚本的超时时间为5秒
driver.manage().timeouts().setScriptTimeout(5, TimeUnit.SECONDS);
// 设置页面加载超时时间为5秒
driver.manage().timeouts().pageLoadTimeout(5, TimeUnit.SECONDS);
特殊元素定位与操作-模态框
Modal Dialogue Box ,又叫做模式对话框,是指在用户想要对对话框以外应用程序进行操作时,必须首先对该对话框进行响应。如:单击确定或取消按钮将该对话框关闭。
-
alert
ChromeDriver driver = Drivers.getChromeDriver();
driver.get("http://127.0.0.1:5500/alert.html");
Thread.sleep(3000);
driver.findElement(By.id("btn")).click();
// switchTo().alert 找到对应的alert 弹窗
Alert alert = driver.switchTo().alert();
// accept() 表示确认 相当于点击了一次确定按钮
Thread.sleep(3000);
//alert.accept();
// getText() 获取文本信息
System.out.println(alert.getText());
// dismiss() 取消
alert.dismiss();
// 获取文本
-
confirm
driver.findElement(By.id("conf")).click();
Thread.sleep(3000);
Alert conf = driver.switchTo().alert();
System.out.println(conf.getText());
// 确认
conf.accept();
Alert alert = driver.switchTo().alert();
Thread.sleep(2000);
System.out.println(alert.getText());
alert.accept();
driver.findElement(By.id("conf")).click();
Thread.sleep(3000);
Alert conf1 = driver.switchTo().alert();
System.out.println(conf1.getText());
// 取消
conf.dismiss();
Alert alert1 = driver.switchTo().alert();
Thread.sleep(2000);
System.out.println(alert1.getText());
alert.accept();
特殊元素定位与操作-iframe
-
iframe 切换
-
driver.switchTo().frame(index)
-
driver.switchTo().frame(id)
-
driver.switchTo().frame(name)
-
driver.switchTo()(WebElement)
-
切换之后,回到默认内容页面(否则会找不到元素)
driver.switchTo().defaultContent()
-
代码实例:
A.HTML页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <h2>这是A.html页面 <input type="text" placeholder="input anything"></h2> <iframe src="./b.html" frameborder="1" width="800px" height="800px" ></iframe> </body> </html>
B.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body style="background-color: pink;"> <h3>这是B.html页面 <input type="text" placeholder="input anything"></h3> <iframe src="./c.html" frameborder="1" width="600px" height="600px"></iframe> </body> </html>
C.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body style="background-color: aqua;"> <h4>这是C.html页面 <input type="text" placeholder="input anything"></h4> </body> </html>
测试程序:
ChromeDriver driver = Drivers.getChromeDriver(); driver.get("http://127.0.0.1:5500/a.html"); Thread.sleep(3000); // 进入第一个页面中的iframe中定位元素并输入数据 iframe 的index从 0 开始计算 driver.switchTo().frame(0); driver.findElement(By.tagName("input")).sendKeys("B frame"); // 进入第二个iframe 并定位元素输入内容 driver.switchTo().frame(0); driver.findElement(By.tagName("input")).sendKeys("C frame"); // 回到默认页面(如果切换到iframe之后不回到默认页面,回出现找不到元素的问题) driver.switchTo().defaultContent(); driver.findElement(By.tagName("input")).sendKeys("A.html");
特殊元素定位-window
-
当你要操作另外一个窗口页面的元素时,一定要注意先切换窗口
-
切换方式:
传入要操作窗口的 name 或者句柄 handle
-
如何获取窗口句柄:
-
driver.getWindowHandle(); // 获取当前窗口句柄
-
driver.getWindowHandles(); // 获取测试时打开的所有窗口句柄
-
-
代码实例:
html代码
a.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>a.html</title> </head> <body> <span>这是A页面</span> <input type="text" placeholder="input anything"> <a href="./b.html" target="_blank">跳转到B页面</a> </body> </html>
b.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>b.html</title> </head> <body> <span>这是B页面</span> <input type="text" placeholder="input anything"> </body> </html>
测试代码:
ChromeDriver driver = Drivers.getChromeDriver();
driver.get("http://127.0.0.1:5500/windowTest/a.html");
System.out.println("window handle: " + driver.getWindowHandle());
driver.findElement(By.tagName("input")).sendKeys("这是A页面");
driver.findElement(By.tagName("a")).click();
Thread.sleep(3000);
System.out.println("window handle: " + driver.getWindowHandle());
System.out.println("-------------------------------");
System.out.println("window handles: " + driver.getWindowHandles());
// 进入到B窗口后,获取所有窗口句柄
Set<String> handles = driver.getWindowHandles();
// 遍历窗口集合
for (String handle : handles) {
// 切换窗口
driver.switchTo().window(handle);
// 通过页面标题判断是否为当前所需页面
if (driver.getTitle().equalsIgnoreCase("b.html")) {
// 如果标题是需要的页面 跳出循环
break;
}
}
// 对B窗口的元素进行定位
driver.findElement(By.tagName("input")).sendKeys("这是B页面了");
特殊元素定位与操作-select下拉框
-
如果页面元素是一个下拉框,我们可以将此 Web 元素封装为 Select 对象:
Select select = new Select(WebElement element);
-
Select 常用 api:
-
select.getOptions(); // 获取所有选项
-
select.selectByIndex(index); // 根据索引选中对应的元素
-
select.selectByValue(value); // 选择指定value值对应的选项
-
select.selectByVisibleText(text); // 选中文本值对应的选项
-
-
代码实例:
html
<select name="" id="" class="filterCondition"> <option value="0">全部</option> <option value="1">教育部</option> <option value="2">国防科工委</option> <option value="3">工业与信息化部</option> <option value="4">中科院</option> <option value="5">社科院</option> <option value="6">外交部</option> <option value="7">中央民委</option> <option value="8">解放军总政</option> <option value="9">公安部</option> </select>
测试代码:
ChromeDriver driver = Drivers.getChromeDriver();
driver.get("http://localhost/website/manage/home.html");
Thread.sleep(3000);
WebElement deptElement = driver.findElement(By.xpath("//*[@id=\"app\"]/section/article[2]/div[2]/div/form/div[3]/select"));
Select select = new Select(deptElement);
select.selectByIndex(2);
Thread.sleep(3000);
select.selectByValue("7");
Thread.sleep(3000);
select.selectByVisibleText("中科院");
特殊元素定位与操作-时间日期控件
-
控件没有限制手动输入,则直接调用 sendKeys() 方法写入时间数据
-
控件有限制手动输入,则可以执行一段 js 来改变元素的 value 属性值
JavascriptExecutor jsExecutor = (JavascriptExecutor)driver; jsExecutor.executeScript('需要执行的代码');
-
代码实例:
允许手动输入的控件进行手动输入(测试网站:飞猪网)
ChromeDriver driver = Drivers.getChromeDriver(); // 日期时间控件可以手动收入 飞猪网 driver.get("https://www.fliggy.com/"); Thread.sleep(3000); WebElement from = driver.findElement(By.xpath("//input[@name='depDate' and @tabindex=3]")); // 没有限制手动输入的时候 可以直接输入数据 from.sendKeys("2021-05-01"); from.sendKeys(Keys.ENTER);
不允许手动输入的日期控件,通过JS脚本修改属性值后进行手动输入(测试网站:12306)
ChromeDriver driver = Drivers.getChromeDriver();
driver.get("https://www.12306.cn");
// 定义修改属性值的 js 脚本
String js = "document.getElementById('train_date').removeAttribute('readonly')";
Thread.sleep(1000);
// 将 driver 强转为 JavascriptExecutor 对象
JavascriptExecutor jsExecutor = (JavascriptExecutor)driver;
// 执行 js 脚本
jsExecutor.executeScript(js);
WebElement dateElement = driver.findElement(By.id("train_date"));
dateElement.clear();
Thread.sleep(1000); dateElement.sendKeys("2021-03-11");
特殊元素定位与操作-鼠标操作
自动化测试时,有些元素不适合直接点击或者进行某些操作,可以使用 Selenium 的 Actions 类来模拟鼠标键盘操作,通过 Actions 对象可以发起鼠标左键、右键、移动鼠标等操作,最后使用 perform() 方法来执行操作
actions.clickAndHold(onElement).moveToElement(toElement).release().build().perform();
测试网址:http://www.treejs.cn/v3/demo/cn/exedit/drag.html
-
代码实例:
// 将 sourceElement 元素拖到 targetElement 元素去 ChromeDriver driver = Drivers.getChromeDriver(); driver.get("http://www.treejs.cn/v3/demo/cn/exedit/drag.html"); WebElement sourcElement = driver.findElement(By.id("treeDemo_2_span")); WebElement targetElement = driver.findElement(By.id("treeDemo_3_span")); Thread.sleep(3000); Actions actions = new Actions(driver); // 以下两种方法执行结果相同 //actions.dragAndDrop(sourcElement, targetElement).release().build().perform(); actions.clickAndHold(sourcElement).moveToElement(targetElement).release().build().perform();
由于 WebDriver 要模拟真实的用户操作,因此 WebDriver 的 Action 类中提供了很多于操作相关的方法:
-
keyDown 模拟按键按下
-
keyUp 模拟按键弹起
-
click 模拟点击
-
sendKeys 模拟键盘输入
-
doubleClick 模拟鼠标左键双击操作
-
clickAndHold 模拟鼠标左键点击并按住不放
-
release 模拟鼠标左键弹起, 可以与 clickAndHold 配合使用
-
moveToElement 把鼠标移动到元素的中心点
-
contextClick 模拟鼠标右键点击
-
dragAndDrop 模拟拖拽
Robot类
Robot类用于为测试自动化、自运行演示程序和其他需要控制鼠标和键盘的应用该程序生成本机系统输入事件。 Robot 的主要目的是便于 Java 平台实现自动测试。
Robot类生成输入事件与将事件发送到 AWT 事件队列。和 AWT 组件的区别在于:事件是在平台的本机输入队列中生成的。
Robot类常用的方法:
-
void delay(int ms) 睡眠指定的时间(类似于线程中 sleep)
-
void keyPress(int keycode) 按下指定的键
-
void keyRelease(int keycode) 释放指定的键
-
void mouseMove(int x, int y) 将鼠标移动到给定的屏幕位置
-
void mousePress(int buttons) 按下一个或多个鼠标按键
-
void mouseRelease(int buttons) 释放一个或多个鼠标按键
-
void mouseWheel(int wheelAmt) 滚动鼠标滚轮
特殊文件定位与操作-文件上传
-
类似于下面,使用 sendKeys 写入文件的路径
<input type="file" id="fu" value="选择文件">
-
如果文件上传不是input 元素,而是使用的第三方控件,并且不是input,这种情况就比较麻烦了,必须使用第三方的工具,比如 autoit 等来完成
-
代码实例:
input元素上传:
ChromeDriver driver = Drivers.getChromeDriver(); driver.get("http://127.0.0.1:5500/upload/upload.html"); Thread.sleep(2000); driver.findElement(By.xpath("//input[@type='file']")).sendKeys("d:\\test.png");
特殊元素定位于操作-验证码
-
去除验证码
-
自动识别
-
万能验证码(推荐)
代码检查点常用方法
-
判断元素是否存在:方式比较多,可以单独封装,也可以直接判断,比如:
try { WebElement el = driver.findElementBy(By.xpath("//*[text()='xxxx']")); } catch(Exception e) { System.out.println("元素不存在"); }
-
判断页面是否存在某些文字: By.xpath("//*[contains(xxx,'xxxx')]")
-
判断页面元素是否在页面上可用或可被点击: ExpectedConditions.elementToBeClicked(By locator)
-
判断页面元素处于被选中状态: ExpectedConditions.elementToBeSelected(WebElement element)
-
判断页面元素在页面中存在: ExpectedConditions.presenceOfElementLocated(By locator)
-
判断页面元素中是否包含特定文本: ExpectedConditions.textToBePresentInElement(By locator)
-
判断字体/背景颜色 element.getCssValue("color") //css属性名称
-
验证元素属性 elemen.getAttribute(attributeName)
代码检查点-TestNG断言
TestNG中常用的断言方法:
-
assertTrue: 判断是否为 true
-
assertFalse: 判断是否为 false
-
assertSame: 判断引用地址是否相同
-
assertNotSame: 判读引用地址是否不同
-
assertNull: 判断是否为 null
-
assertNotNull: 判断是否不为 null
-
assertEquals: 判断是否相等, Object类型的对象需要实现 haseCode 及 equals 方法
-
assertNotEquals: 判断是否不相等
-
assertEqualsNoOrder: 判断是否相等(忽略排序)