WebDriver相关api
定位一组元素
webdriver可以很方便地使用findElement方法来定位某个特定的对象, 不过有时候我们需要定位一组对象, 这时候就要使用findElements方法.
定位一组对象一般用于一下场景:
批量操作对象, 比如将页面上的checkbox都勾上.
先获取一组对象, 再在这组对象中过滤出需要具体定位的对象. 比如定位出页面上的checkbox, 然后选取最后一个.
通过类似下面这种形式可以定位一组元素.
List<WebElement> webElements = webDriver.findElements(.......);
下面我们在实际场景下使用一下, 先给出我们需要用到的html代码, 放入resource即可:
<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>
测试代码如下:
private static void test10() {
WebDriver webDriver = new ChromeDriver();
//这个是提供前端代码在文件中的路径
webDriver.get("file:///C:/Users/86133/Desktop/%E6%96%87%E7%AB%A0/%E8%AF%BE%E4%BB%B6/html/%E6%B5%8B%E8%AF%95%E7%94%A8/test01.html");
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.DAYS);
//找到所有的input框
List<WebElement> webElements = webDriver.findElements(By.cssSelector("input"));
for(int i = 0; i < webElements.size(); i++) {
//如果每个元素type等于checkbox进行点击(注:这里可能是radio-单选框, checkbox-多选框)
//getAttribute获取页面的属性值, 比对
if(webElements.get(i).getAttribute("type").equals("checkbox")) {
webElements.get(i).click();
}
}
}
测试结果:
可以看到成功地完成了多选.
多层框架/窗口定位
对于一个web应用, 经常会出现框架(frame)或窗口(window)的应用, 这也就给我们的定位带来了一定的困难.
窗口是操作系统中的基本用户界面元素, 用于承载应用程序的可视化界面, 通常由标题栏, 菜单栏, 工具栏, 客户区和边框组成. 而框架是一种高级的GUI组件, 用于创建具有特定功能和外观的窗口, 通常是窗口的一种特殊类型或子类,具有额外的功能和布局选项.
定位一个frame: webDriver.switchTo().frame()
定位一个窗口window: webDriver.switchTo().window()
多层框架的定位
switchTo.frame(): 通过frame的id或者name或者frame自带的其它属性来定位框架, 这里switchTo().frame()把当前定位的主体切换到了frame里.
webDriver.switchTo().defaultContent(): 从frame中嵌入的页面里跳出, 跳回到最外面的默认页面中.
下面我们来测试一下(需求: 定位到inner, 并点击click), 先给出外层frame的html代码:
<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>
inner.html:
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>inner</title>
</head>
<body>
<div class="row-fluid">
<div class="span6 well">
<h3>inner</h3>
<iframe id="f2" src="https://www.baidu.com/"
width="700"height="500"></iframe>
<a href="javascript:alert('watir-webdriver better than selenium webdriver;')">click</a>
</div>
</div>
</body>
</html>
测试代码:
private static void test11() {
WebDriver webDriver = new ChromeDriver();
webDriver.get("file:///C:/Users/86133/Desktop/%E6%96%87%E7%AB%A0/%E8%AF%BE%E4%BB%B6/html/%E6%B5%8B%E8%AF%95%E7%94%A8/test02.html");
webDriver.switchTo().frame("f1");
webDriver.findElement(By.cssSelector("body > div > div > a")).click();
}
运行结果(建议自行测试):
这时可以看到成功定位了, 并完成了指定的点击操作.
多层窗口定位
有可能嵌套的不是框架, 而是窗口, 还有针对窗口的方法: switchTo.window("windowName");
下拉框处理
下拉框是我们最常见的一种页面元素, 对于一般的元素, 我们只需要一次就定位, 但是对于下拉框里的内容需要进行两次定位, 先定位到下拉框对下拉框进行操作时, 在定位到下拉框里的选项.
测试一下, 先给出html代码:
<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>
现在我们来选择性地定位元素:
private static void test12() throws InterruptedException {
WebDriver webDriver = new ChromeDriver();
webDriver.get("file:///C:/Users/86133/Desktop/%E6%96%87%E7%AB%A0/%E8%AF%BE%E4%BB%B6/html/%E6%B5%8B%E8%AF%95%E7%94%A8/test03.html");
//定位到下拉框
WebElement webElement = webDriver.findElement(By.cssSelector("#ShippingMethod"));
//创建Select对象来操作下拉框列表
Select select = new Select(webElement);
sleep(3000);
//选择到第3个元素(下标从0开始)
select.selectByIndex(3);
sleep(3000);
//选择到值为12.51的元素
select.selectByValue("12.51");
}
请自行测试以查看结果.
弹窗操作
有时候在页面中可能会"蹦出"一些弹窗, 那么我们应该怎么对弹窗操作呢? 下面给出几种操作方法:
我们通过 switch().alert()来对弹窗进行操作, 下面给出几种常见的操作组合:
1.弹窗确认: switchTo().alert().accept();2.弹窗取消: switchTo().alert().dismiss();
3.向弹窗中输入内容: switchTo().alert().sendKeys(".....");
下面我们给出html代码,我们来测试一下:
<!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>
测试代码:
private static void test13() throws InterruptedException {
WebDriver webDriver = new ChromeDriver();
webDriver.get("file:///C:/Users/86133/Desktop/%E6%96%87%E7%AB%A0/%E8%AF%BE%E4%BB%B6/html/%E6%B5%8B%E8%AF%95%E7%94%A8/test04.html");
//找到"这是一个弹窗"按钮并点击
webDriver.findElement(By.cssSelector("button")).click();
sleep(3000);
//弹窗取消
webDriver.switchTo().alert().dismiss();
sleep(3000);
webDriver.findElement(By.cssSelector("button")).click();
//在弹窗中输入内容
webDriver.switchTo().alert().sendKeys("初音未来");
//弹窗确认
sleep(3000);
webDriver.switchTo().alert().accept();
}
选择文件并放置
这个与输入类似, 使用sendKeys()操作即可.
eg: webDriver.findElement(By.cssSelector("")).sendKeys("文件路径");
跳转页面选择元素
在前面, 我们学习了在一个页面中选择元素, 就是通过一个元素的标签或者类名什么的来进行定位. 那么我要问一个问题, 在当前页面中选择一个元素, 再在会跳转到的页面选择一个元素, 那么这个元素还生效吗? 我们不妨来测试一下:
比如先在百度首页点击新闻, 然后跳转后输入新闻联播:
按照先前的方法, 我们来测试一下:
我们发现这里报错了, 这里我们得出结论:
在页面跳转后, 已选择的下拉表元素可能会丢失选中状态, 这取决于页面的实现和浏览器的行为(即你要找的元素默认是在get方法打开的页面来寻找的). 通常情况下, 页面跳转后, 之前的页面会被清除, 包括下拉列表的选中状态. 并且还有一个问题,跳转后的页面和当前的页面可能会出现id一致的问题.
那么我们应该怎么解决这个问题呢?
针对上面发现的问题, 就是出现在,页面跳转后丢失了选中状态, 所以我们应该在页面跳转之后保持选中状态, 可以考虑在页面跳转前记录当前选中的选项值, 并在跳转后再次选中该值. 或者在页面跳转后重新定位到下拉列表元素, 并重新选择之前选中的选项.
那么怎么实现呢?
这就使用到了获取句柄的方法.
句柄的定义: 总的来说, 句柄是一个通用的概念, 用来引用和操作各种对象. 它提供了一种抽象的方式来管理和访问对象, 使得程序能够更灵活地进行处理.
在Selenium WebDriver中, getWindowHandle()和getWindowHandles()方法用于处理浏览器窗口和标签页的句柄.
1.getWindowHandle(): 这个方法用于获取当前浏览器窗口或标签页的句柄(handle). 句柄是一个字符串, 表示当前窗口或标签页的唯一标识符.
String currentWindowHandle = webDriver.getWindowHandle();
2.getWindowHandles(): 这个方法用于获取当前浏览器所有窗口或标签页的句柄集合. 返回的是一个包含所有窗口句柄的集合.
Set<String> windowHandles = webDriver.getWindowHandles();
修改一下代码:
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();
Thread.sleep(3000);
//通过getWindowHandles获取所有的窗口句柄
//通过getWindowHandle获取的get打开的页面窗口句柄.
System.out.println(webDriver.getWindowHandle());
//获取到所有的窗口句柄,存储到一个set集合中
Set<String> handles = webDriver.getWindowHandles();
String target_handle = "";
for(String handle : handles) {
target_handle = handle;
}
//这个就是打开新窗口的句柄
webDriver.switchTo().window(target_handle);
Thread.sleep(3000);
webDriver.findElement(By.cssSelector("#ww")).sendKeys("新闻联播");
webDriver.findElement(By.cssSelector("#s_btn_wr")).click();
}
运行, 发现能够正确处理逻辑了.
截图功能
这里直接给出代码:
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();
Thread.sleep(3000);
//使用WebDriver截图功能进行页面截图, 首先将WebDriver强制转换为TakesScreenshot接口
//然后调用getScreenshotAs方法获取截图文件
File file = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);
//使用FileUtils工具将截图文件保存到本地
FileUtils.copyFile(file, new File("D://2024419jietu.png"));
}
运行代码, 发现截图成功: