三. 掌握Selenium常用的API使用
一次完整的测试流程:
代码语言:javascript复制 public static void test01() throws InterruptedException {
int flag = 0;
ChromeOptions options = new ChromeOptions();
//允许所有请求
options.addArguments("--remote-allow-origins=*");
WebDriver webDriver = new ChromeDriver();
//打开百度首页
webDriver.get("https://www.baidu.com");
//找到百度搜索输入框
WebElement element = webDriver.findElement(By.xpath("//*[@id="kw"]"));
//输入"软件测试(要搜索的内容)"
element.sendKeys("软件测试");
//找到百度一下按钮
//点击
webDriver.findElement(By.cssSelector("#su")).click();
sleep(3000);
//校验
//找到搜索结果
List<WebElement> elements = webDriver.findElements(By.cssSelector("a em"));
for(int i = 0; i < elements.size(); i ) {
// 如果返回的结果有软件测试,证明测试通过,否则测试不通过
if(elements.get(i).getText().equals("测试")) {
flag = 1;
System.out.println("测试通过");
break;
}
}
if(flag == 0) {
System.out.println("测试不通过");
}
}
1. webdriver API
css
选择语法
public static void main(String[] args) {
ChromeOptions options = new ChromeOptions();
//允许所有请求
options.addArguments("--remote-allow-origins=*");
WebDriver webDriver = new ChromeDriver();
//打开百度首页
webDriver.get("https://www.baidu.com");
//找到百度搜索输入框
WebElement element = webDriver.findElement(By.cssSelector(".s_ipt"));
//输入"软件测试(要搜索的内容)"
element.sendKeys("软件测试");
}
2. Xpath
定位元素
点击复制后:
代码语言:javascript复制 public static void main(String[] args) {
ChromeOptions options = new ChromeOptions();
//允许所有请求
options.addArguments("--remote-allow-origins=*");
WebDriver webDriver = new ChromeDriver();
//打开百度首页
webDriver.get("https://www.baidu.com");
//找到百度搜索输入框
WebElement element = webDriver.findElement(By.xpath("//*[@id="kw"]"));
//输入"软件测试(要搜索的内容)"
element.sendKeys("软件测试");
}
关于Xpath的详细语法见: Xpath教程
面试题:css选择器和Xpath选择器的常见语法有哪些? css选择器:
- 元素选择器:通过元素名称来选择对应的元素。语法形式为"元素名称",例如"div"表示选择所有的div元素。
- 类选择器:通过元素的class属性值来选择对应的元素。语法形式为".class值",例如".myClass"表示选择class属性值为"myClass"的所有元素。
- ID选择器:通过元素的id属性值来选择对应的元素。语法形式为"#id值",例如"#myElement"表示选择id属性值为"myElement"的元素
- 属性选择器:通过元素的属性和属性值来选择对应的元素。语法形式为"[属性=‘属性值’]“,例如”[href=‘https://example.com’]"表示选择href属性值为"https://example.com"的所有元素。
- 伪类选择器:通过元素的特定状态或位置来选择对应的元素。常见的伪类选择器包括:hover(鼠标悬停)、:first-child(第一个子元素)、:last-child(最后一个子元素)等。
Xpath选择器:
- 绝对路径:/html/head/title(不常用)
- 相对路径:
(1)相对路径 索引:
//from/span[1]/input
(2)相对路径 属性值 ://input[@class="s_ipt"]
(3)相对路径 通配符:// *[@* = "su"]
(4)相对路径 文本匹配://a[text()="新闻"]
面试题: (1)定位一个元素有哪几种方式(你是通过什么方式定位元素的?) 答:CSS选择器,Xpath定位元素. (2)CSS选择器和Xpath选择器哪个更好? CSS选择器定位元素更高效.
2. 操作测试对象
操作 | 说明 |
---|---|
click | 点击对象 |
send_keys | 在对象上模拟按键输入 |
clear | 清除对象输入的文本内容 |
submit | 提交 |
text | 用于获取元素的文本信息 |
getAttribute | 获取属性 |
此处我们主要讲解clear
以及submit
.
clear
操作:
private static void test02() {
ChromeOptions options = new ChromeOptions();
//允许所有请求
options.addArguments("--remote-allow-origins=*");
WebDriver webDriver = new ChromeDriver();
webDriver.get("https://www.baidu.com/");
// 找到百度搜索输入框输入"猫咪"
webDriver.findElement(By.cssSelector("#kw")).sendKeys("猫咪");
// 点击百度一下按钮
webDriver.findElement(By.cssSelector("#su")).click();
// 清空输入框中的数据
webDriver.findElement(By.cssSelector("#kw")).clear();
}
submit
操作:
webDriver.findElement(By.cssSelector("#su")).submit();
我们可以看到,submit
和click
的效果是一样的,但是submit
存在一定的弊端:
如果点击的元素放在form标签中,此时使用submit实现的效果和click是一样的.如果点击的元素放在非form标签中,此时使用submit会报错!
如下:(此时submit操作的不是from标签下的元素)
一般情况下,我们就使用click.
getAttribute
操作:
private static void test04() {
ChromeOptions options = new ChromeOptions();
options.addArguments("--remote-allow-origins=*");
WebDriver webDriver = new ChromeDriver(options);
webDriver.get("https://www.baidu.com/");
String button_value = webDriver.findElement(By.cssSelector("#su")).getAttribute("value");
// System.out.println(button_value);
if(button_value.equals("百度一下")) {
System.out.println("测试通过");
} else {
System.out.println(button_value);
System.out.println("测试不通过");
}
}
3. 添加等待
- sleep强制等待
- 智能等待:隐式等待,显示等待
假设等待三天时间: 强制等待一直等待,等待的时间为三天. 隐式等待,最长等待三天时间,如果在三天之内获取到页面上的元素,此时执行下面的代码,如果等待三天还是没有找到这个元素,就会报错.
强制等待:
智能等待: 隐式等待:
代码语言:javascript复制 private static void test02() throws InterruptedException {
ChromeOptions options = new ChromeOptions();
//允许所有请求
options.addArguments("--remote-allow-origins=*");
WebDriver webDriver = new ChromeDriver();
webDriver.get("https://www.baidu.com/");
// 找到百度搜索输入框输入"猫咪"
webDriver.findElement(By.cssSelector("#kw")).sendKeys("猫咪");
// 点击百度一下按钮
webDriver.findElement(By.cssSelector("#su")).submit();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.DAYS);
// 清空输入框中的数据
webDriver.findElement(By.cssSelector("#kw")).clear();
}
智能等待:显示等待:
代码语言:javascript复制 private static void test06() {
// #bottom_layer > div > p:nth-child(8) > span
// 创建驱动
WebDriver webDriver = new ChromeDriver();
// 打开百度首页
webDriver.get("https://www.baidu.com/");
// 判断元素是否可以被点击
WebDriverWait wait = new WebDriverWait(webDriver, 1);
// wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#bottom_layer > div > p:nth-child(8)")));
wait.until(ExpectedConditions.titleIs("百度一下,你就知道"));
}
此处需要注意隐式等待和显示等待的区别:
- 作用范围:隐式等待是全局性的等待设置,适用于整个页面的元素定位操作;显示等待是针对特定元素或条件的等待设置,更具体、可定制性更强。
- 等待时间:隐式等待只需设置一次,并适用于所有元素的定位操作;显示等待可以根据不同情况设定不同的等待时间。
- 等待条件:隐式等待没有明确的等待条件,只要在规定时间内找到元素即可;显示等待可以指定等待元素可见、可点击等特定条件。
- 操作方式:隐式等待是自动等待的,不需要在代码中显式调用;显示等待需要在代码中显式调用等待方法。
4. 打印信息
打印url
&&打印title
private static void test05() {
ChromeOptions options = new ChromeOptions();
options.addArguments("--remote-allow-origins=*");
WebDriver webDriver = new ChromeDriver(options);
webDriver.get("https://www.baidu.com/");
String url = webDriver.getCurrentUrl();
String title = webDriver.getTitle();
if(url.equals("https://www.baidu.com/") && title.equals("百度一下,你就知道")) {
System.out.println("当前页面url:" url ",当前页面title:" title);
System.out.println("测试通过");
} else {
System.out.println("测试不通过");
}
}
5. 浏览器的操作
操作 | 说明 |
---|---|
browser.maximize_window() | 浏览器的最大化 |
browser.set_window_size(width, high) | 设置浏览器宽、高 |
browser.forward() | 浏览器的前进 |
browser.back() | 浏览器的后退 |
document.documentElement.scrollTop=0 | 将浏览器滚动条滑到最顶端 |
document.documentElement.scrollTop=10000 | 将浏览器滚动条滑到最底端 |
- 浏览器前进,后退,刷新操作
private static void test07() throws InterruptedException {
WebDriver webDriver = new ChromeDriver();
// 打开百度首页
webDriver.get("https://wwww.baidu.com/");
// 搜索521
webDriver.findElement(By.cssSelector("#kw")).sendKeys("521");
// 强制等待3秒
webDriver.findElement(By.cssSelector("#su")).click();
// 浏览器后退
sleep(3000);
webDriver.navigate().back();
// 强制等待3秒
sleep(3000);
//浏览器刷新
webDriver.navigate().refresh();
// 浏览器前进
sleep(3000);
webDriver.navigate().forward();
3. 浏览器滚动条操作,窗口操作
代码语言:javascript复制 private static void test07() throws InterruptedException {
WebDriver webDriver = new ChromeDriver();
// 打开百度首页
webDriver.get("https://wwww.baidu.com/");
// 搜索521
webDriver.findElement(By.cssSelector("#kw")).sendKeys("521");
// 强制等待3秒
webDriver.findElement(By.cssSelector("#su")).click();
//滚动条操作
sleep(3000);
//网页的滚动条会自动向下滚动至10000像素的位置
((JavascriptExecutor)webDriver).executeScript("document.documentElement.scrollTop=10000");
sleep(3000);
//窗口最大化
webDriver.manage().window().maximize();
sleep(3000);
//窗口全屏
webDriver.manage().window().fullscreen();
sleep(3000);
//设置指定窗口大小
webDriver.manage().window().setSize(new Dimension(600, 1000));
}
6. 键盘事件
操作 | 说明 |
---|---|
send_keys(Keys.TAB) | # TAB |
send_keys(Keys.ENTER) | # 回车 |
send_keys(Keys.SPACE) | #空格键 |
send_keys(Keys.ESCAPE) | #回退键(Esc) |
send_keys(Keys.CONTROL,‘a’) | #全选(Ctrl A) |
send_keys(Keys.CONTROL,‘c’) | #复制(Ctrl C) |
send_keys(Keys.CONTROL,‘x’) | #剪贴(Ctrl X) |
send_keys(Keys.CONTROL,‘v’) | #粘贴(Ctrl V) |
键盘的全选,剪切,粘贴操作演示:
代码语言:javascript复制 private static void test08() throws InterruptedException {
WebDriver webDriver = new ChromeDriver();
// 打开百度首页
webDriver.get("https://wwww.baidu.com/");
// 搜索521
webDriver.findElement(By.cssSelector("#kw")).sendKeys("521");
// control A
webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL, "A");
sleep(3000);
// control X
webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL, "X");
sleep(3000);
// control V
webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL, "V");
sleep(3000);
}
7. 鼠标事件
操作 | 说明 |
---|---|
context_click() | 右击 |
double_click() | 双击 |
drag_and_drop() | 拖动 |
move_to_element() | 移动 |
context_click()
演示:
private static void test09() throws InterruptedException {
WebDriver webDriver = new ChromeDriver();
webDriver.get("https://www.baidu.com/");
webDriver.findElement(By.cssSelector("#kw")).sendKeys("520");
webDriver.findElement(By.cssSelector("#su")).click();
sleep(3000);
// 找到图片按钮
WebElement webElement = webDriver.findElement(By.cssSelector("#s_tab > div > a.s-tab-item.s-tab-item_1CwH-.s-tab-pic_p4Uej.s-tab-pic"));
// 鼠标右击出现框
Actions actions = new Actions(webDriver);
sleep(3000);
//contextClick()右击鼠标
actions.moveToElement(webElement).contextClick().perform();
}
8. 定位一组元素
webdriver
可以很方便的使用findElement
方法来定位某个特定的对象,不过有时候我们却需要定位一组对象,这时候就需要使用findElements
方法。
定位一组对象一般用于以下场景:
- 批量操作对象,比如将页面上所有的
checkbox
都勾上 - 先获取一组对象,再在这组对象中过滤出需要具体定位的一些对象。比如定位出页面上所有的checkbox,然后选择最后一个 有如下界面:
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>Checkbox</title>
</head>
<body>
<h3>checkbox</h3>
<div class="well">
<form class="form-horizontal">
<div class="control-group">
<label class="control-label" for="c1">checkbox1</label>
<div class="controls">
<input type="checkbox" id="c1" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="c2">checkbox2</label>
<div class="controls">
<input type="checkbox" id="c2" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="c3">checkbox3</label>
<div class="controls">
<input type="checkbox" id="c3" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="r">radio</label>
<div class="controls">
<input type="radio" id="r1" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="r">radio</label>
<div class="controls">
<input type="radio" id="r2" />
</div>
</div>
</form>
</div>
</body>
</html>
findElements
示例(将页面上所有的checkbox
都勾上):
private static void page01() {
WebDriver webDriver = new ChromeDriver();
webDriver.get("http://localhost:63342/_20230925testcode/src/main/Page/test01.html?_ijt=hk3glm0bcb2222roak6kf4826i&_ij_reload=RELOAD_ON_SAVE");
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.DAYS);
List<WebElement> webElements = webDriver.findElements(By.cssSelector("input"));
for(int i = 0; i < webElements.size(); i ) {
// 如果每个元素type值等于checkbox进行点击
// getAttribute获取页面上的元素属性值,里面的type是当前元素属性
if(webElements.get(i).getAttribute("type").equals("checkbox")){
webElements.get(i).click();
} else {
// 否则什么也不操作
;
}
}
}
9. 多层框架/窗口定位
对于一个web应用,经常会出现框架(yrame或窗口(window)的应用,这也就给我们的定位带来了一定的困难。
- 定位一个frame :
switch_to.frame(name_or_id_or_frame_element)
- 定位一个窗口window:
switch_to.window(name_or_id_or_frame_element)
有以下页面:
代码语言:javascript复制<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>frame</title>
<!-- <link href="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" />-->
<script type="text/javascript">$(document).ready(function(){
});
</script>
</head>
<body>
<div class="row-fluid">
<div class="span10 well">
<h3>frame</h3>
<iframe id="f1" src="inner.html" width="800", height="600"></iframe>
</div>
</div>
</body>
<!--<script src="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>-->
</html>
frame
演示:
private static void page02() {
WebDriver webDriver = new ChromeDriver();
webDriver.get("http://localhost:63342/_20230925testcode/src/main/Page/test02.html?_ijt=sdck9iv3t1f7l8bv2khvu2k87t&_ij_reload=RELOAD_ON_SAVE");
webDriver.switchTo().frame("f1");
webDriver.findElement(By.cssSelector("body > div > div > a")).click();
}
10. 下拉框处理
有以下界面:
代码语言:javascript复制<html>
<body>
<select id="ShippingMethod" onchange="updateShipping(options[selectedIndex]);" name="ShippingMethod">
<option value="12.51">UPS Next Day Air ==> $12.51</option>
<option value="11.61">UPS Next Day Air Saver ==> $11.61</option>
<option value="10.69">UPS 3 Day Select ==> $10.69</option>
<option value="9.03">UPS 2nd Day Air ==> $9.03</option>
<option value="8.34">UPS Ground ==> $8.34</option>
<option value="9.25">USPS Priority Mail Insured ==> $9.25</option>
<option value="7.45">USPS Priority Mail ==> $7.45</option>
<option value="3.20" selected="">USPS First Class ==> $3.20</option>
</select>
</body>
</html>
通过Index
和Value
来选择演示:
private static void page03() {
WebDriver webDriver = new ChromeDriver();
webDriver.get("http://localhost:63342/_20230925testcode/src/main/Page/test03.html?_ijt=ibu1q228hs9l4q026vbbfjp8r3&_ij_reload=RELOAD_ON_SAVE");
WebElement webElement = webDriver.findElement(By.cssSelector("#ShippingMethod"));
Select select = new Select(webElement);
//通过下标来选择
// select.selectByIndex(3);
//通过value值来选择
select.selectByValue("12.51");
}
11. 弹窗处理
有以下页面:
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button onclick="Click()">这是一个弹窗</button>
</body>
<script type="text/javascript">
function Click() {
let name = prompt("请输入姓名:");
let parent = document.querySelector("body");
let child = document.createElement("div");
child.innerHTML = name;
parent.appendChild(child)
}
</script>
</html>
alert
相关操作:
private static void page04() throws InterruptedException {
WebDriver webDriver = new ChromeDriver();
webDriver.get("http://localhost:63342/_20230925testcode/src/main/Page/test04.html?_ijt=bv9np3tl8gm9kv04oam7i2sfij&_ij_reload=RELOAD_ON_SAVE");
webDriver.findElement(By.cssSelector("button")).click();
sleep(3000);
// alert弹窗取消
webDriver.switchTo().alert().dismiss();
sleep(3000);
// 点击按钮
webDriver.findElement(By.cssSelector("button")).click();
// 在alert弹窗中输入"xxxflower"
webDriver.switchTo().alert().sendKeys("xxxflower");
// alert弹窗确认
sleep(3000);
webDriver.switchTo().alert().accept();
}
12. 上传文件
上传过程一般要打开一个本地窗口,从窗口选择本地文件添加。所以,一般会卡在如何操作本地窗口添加上传文件。
其实,在selenium webdriver
没我们想的那么复杂;只要定位上传按钮,通过send_keys 添加本地文件路径就可以了。绝对路径和相对路径都可以,关键是上传的文件存在.
private static void page05() {
WebDriver webDriver = new ChromeDriver();
webDriver.get("http://localhost:63342/_20230925testcode/src/main/Page/test05.html?_ijt=16g56va44mth0ok9g9lfkdqj32&_ij_reload=RELOAD_ON_SAVE");
webDriver.findElement(By.cssSelector("input")).sendKeys("E:\壁纸\haimianbaobao.png");
}
13. 关闭浏览器
关闭浏览器有两种方式,分别为
quit();
close();
需要注意的是quit();
和close
之间的区别:
(1)quit关闭了整个浏览器,close关闭了当前的页面.
close的当前页面指的是操作的该页面,也就是百度首页.
(2)quit清空缓存,close不会清空缓存
quit();
和close();
的演示:
private static void test10() throws InterruptedException {
WebDriver webDriver = new ChromeDriver();
webDriver.get("https://www.baidu.com/");
//找到新闻按钮
webDriver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();
sleep(2000);
webDriver.quit();
// webDriver.close();
}
quit();
close();
14. 切换窗口
当我们从百度页面打开新闻页面的时候,此时我们如果想要在新闻页面操作百度一下,那么就得切换窗口.即改变句柄(操作的对象).此时我们就可以使用.getWindowHandles();
获取全部的句柄,遍历存储全部句柄的Set
获取到我们需要的最后一个句柄,然后通过webDriver.switchTo().window(target_handle);
切换窗口.于是我们就可以操作新闻页面的百度一下了.
private static void test11() throws InterruptedException {
WebDriver webDriver = new ChromeDriver();
webDriver.get("https://www.baidu.com/");
//找到新闻按钮
webDriver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();
sleep(1000);
// 通过getWindowHandles获取所有的窗口句柄
// 通过getWindowHandle获取的get打开的页面窗口句柄
System.out.println(webDriver.getWindowHandle());
Set<String> handles = webDriver.getWindowHandles();
String target_handle = "";
for(String handle:handles) {
target_handle = handle;
}
webDriver.switchTo().window(target_handle);
sleep(3000);
//在输入框中搜索新闻联播
webDriver.findElement(By.cssSelector("#ww")).sendKeys("新闻联播");
//点击"百度一下"
webDriver.findElement(By.cssSelector("#s_btn_wr")).click();
}
15. 截图操作
引入Maven
依赖:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
截图操作演示:
代码语言:javascript复制 private static void test12() throws InterruptedException, IOException {
WebDriver webDriver = new ChromeDriver();
webDriver.get("https://www.baidu.com/");
webDriver.findElement(By.cssSelector("#kw")).sendKeys("软件测试");
webDriver.findElement(By.cssSelector("#su")).click();
sleep(3000);
//强转成截图对象
File file = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);
//将截图好的图片存储到E://20231005jietu.png路径下
FileUtils.copyFile(file, new File("E://20231005jietu.png"));
}