元素操控
选择到元素之后,我们的代码会返回元素对应的 WebElement对象,通过这个对象,我们就可以 操控
元素
输入sendKeys
项目实战:在网银环境下载流水[交易明细]的时候,需要指定查询日期,有些银行是可以直接输入起止日期的
sendKeys在元素(如输入框元素)中输入字符串
WebElement input = driver.findElement(By.id("key"));
//清空输入框
input.clear();
//在输入框中输入内容
input.sendKeys("蓝牙耳机");
对于input输入框的元素,要获取里面的输入文本
// 找到元素
WebElement element = driver.findElement(By.id("usernameid"));
element.getAttribute("value");
点击click
click点击元素
//单击搜索按钮
driver.findElement(By.xpath("//*[@id='search']/div/div[2]/button")).click();
下拉框[select]
项目实战:在网银环境中选择账号,选择交易类型等等
如下是标准的select标签中,如下:
选择下拉列表中的值呢
- selectByValue 语法
- selectByVisibleText 语法
- select.selectByIndex()语法;
简单场景举例如下,选择下拉框变为 “10进制”转"16进制"
webDriver.get("https://tool.ip138.com/hexconvert/");
//选择10进制
WebElement webElementFrom = webDriver.findElement(By.xpath("//*[@id=\"from_type\"]"));
Select fromDropList = new Select(webElementFrom);
fromDropList.selectByVisibleText("10进制");
//选择16进制
WebElement webElementTo = webDriver.findElement(By.xpath("//*[@id=\"to_type\"]"));
Select toDropList = new Select(webElementTo);
toDropList.selectByVisibleText("16进制");
//打印下拉框中所有的选项
List<WebElement> options = toDropList.getOptions();
for (WebElement option : options) {
System.out.println(option.getText());
}
下拉框[非select]
项目实战:但是更多的网银环境中,选择账号的时候,他不是用的标准的select标签,额....而是使用li标签或者div标签
如下的下拉框
就是用div标签实现的
简单场景举例:
//点击下拉选择账号
driver.findElement(By.xpath("//*[@id=\"PaMng_aQry_aXDtlQry\"]/div[2]/div/div[1]/div[1]/div/div[2]/div/span")).click();
List<WebElement> accountListStr = driver.findElements(By.xpath("//*[@id=\"PaMng_aQry_aXDtlQry\"]/div[2]/div/div[1]/div[1]/div/div[2]/div/div/ul/li"));
System.out.println("accountListStr.size()"+accountListStr.size());
for(int x=0;x<accountListStr.size();x++){
System.out.println(accountListStr.get(x).getText());
//下拉框选择账号8888888
if(accountListStr.get(x).getText().contains("8888888")){
accountListStr.get(x).click();
break;
}
}
操作复选框
项目实战:在网银环境中,下载回单的时候,勾选全选按钮。
可以直接使用点击复选框进行勾选
//点击全选 driver.findElement(By.xpath("//*[@id=\"checkAll\"]")).click();
也可以使用
简单场景举例如下,我们勾选全局搜索和忽略大小写
操作单选框
如下图,我们操作使得打开网站后,选择时间戳为“13位”,因为默认选中的是10位
webDriver.get("https://m.bejson.com/convert/unix/");
//13位时间戳(毫秒级)
WebElement radio = webDriver.findElement(By.xpath("//*[@id=\"kt_post\"]/div/div/div/div/div/form/div[2]/div[1]/div[2]/input"));
//如果处于未选中状态,则单击选中
if (!radio.isSelected()) {
radio.click();
}
链接 link
链接a标签的操作
// 找到链接元素
WebElement link1 = driver.findElement(By.linkText("小坦克"));
WebElement link11 = driver.findElement(By.partialLinkText("坦克"));
// 点击链接
link1.click();
举例:
表格操作
网页表格
寻找一个在线的被测试的网页表格,假设如下:
Personal pronouns table (mdn.github.io)
th和td的区别
<tr>...</tr> 定义一行标签,一组行标签内可以建立多组由<td>或<th>标签所定义的单元格
<th>...</th> 定义表头单元格。表格中的文字将以粗体显示
<td>...</td> 定义单元格标签,一组<td>标签将将建立一个单元格
//创建浏览器实例
WebDriver driver = new ChromeDriver();//打开chrome
driver.get("https://mdn.github.io/learning-area/html/tables/basic/personal-pronouns.html");//打开一个在线的网页表格
//获取页面表格对象
WebElement element = driver.findElement(By.xpath("/html/body/table"));
//获取表格行数
List<WebElement> tr = element.findElements(By.tagName("tr"));
System.out.println("表格行数:" + tr.size());
Action
使用 Action 类来生成用户事件,例如右键单击 WebDriver 中的元素。参考代码片段:
Actions action = newActions(driver);
WebElement element = driver.findElement(By.id("elementId"));
//右键单击元素
action.contextClick(element).perform();
//鼠标悬停
action.moveToElement(element).perform();
拖放
Actions builder = newActions(driver);
Action dragAndDrop = builder.clickAndHold(fromWebElement)
.moveToElement(toWebElement)
.release(toWebElement)
.build();
dragAndDrop.perform();
Web 元素可见性
WebDriver 允许用户检查 Web 元素的可见性。这些网络元素可以是按钮、单选按钮、下拉菜单、复选框、框、标签等,它们与以下方法一起使用。
- isDisplayed()
- isSelected()
- isEnabled()
窗口和标签页
网页访问
方式一:get方法
//访问京东
webDriver.get("https://www.jd.com/");
方式二:
//访问京东
webDriver.navigate().to("https://www.jd.com/");
窗口最大化
一些别的页面操作
1、页面最大化
//将浏览器窗口最大化 webDriver.manage().window().maximize(); //访问京东 webDriver.navigate().to("https://www.jd.com/");
2、获取页面Title属性
//获取页面Title属性 String title = webDriver.getTitle(); System.out.println(title);
3、获取页面的源代码
//访问京东 webDriver.navigate().to("https://www.jd.com/"); //获取网页的源代码 String pageSource = webDriver.getPageSource(); System.out.println(pageSource);
4、刷新页面
driver.navigate().refresh();
标签页切换
在某个页面点击链接打开了一个新的标签页,此时selenium是无法定位到新标签页的元素。
这就涉及到句柄的概念了,句柄就是标签页对象的唯一标识,每个标签页都有自己的句柄,可以通过句柄来实现标签页的切换,从而定位到对应标签页的元素。
//获取当前所有打开的浏览器窗口的句柄
Set<String> windowHandles = webDriver.getWindowHandles();
for (String windowHandle : windowHandles) {
System.out.println(windowHandle);
System.out.println(webDriver.switchTo().window(windowHandle).getTitle());
}
//获取当前浏览器窗口的句柄
String windowHandle = webDriver.getWindowHandle();
System.out.println("当前窗口句柄:"+windowHandle);System.out.println("当前窗口句柄:"+windowHandle);
控制台打印输出如下
根据URL进行切换标签页,如果URL包含对应的字符串的话,则切换到相应标签页。
pub_switchByUrl("ib.cdb.com.cn/b2bmain");
void pub_switchByUrl(String urlPatten){
ar.driver.switchTo().defaultContent();
Set handles = ar.driver.getWindowHandles();
for(String handle : handles){
ar.driver.switchTo().window(handle);
if(ar.driver.getCurrentUrl().contains(urlPatten))
break;
}
}
窗口关闭
- driver.close() 关闭当前标签页
- driver.quit() 关闭所有标签页
webDriver.close()
如果打开了多个页面是关不干净的,close()只关闭当前的一个页面。
使用时要注意 “当前页面” 这四个字,意味着当你关闭新打开的页面时,需要切换窗口才能操作新窗口并将它关闭。
webDriver.quit()
quit()是退出了所有Webdriver所有的窗口,并退出驱动程序。
Frame
iframe标签
HTML 内联框架元素 (<iframe>
) 表示嵌套的browsing context。它能够将另一个 HTML 页面嵌入到当前HTML页面中。
在 HTML 文档中 <frame> 每出现一次,就会创建一个 Frame对象
通常我们使用iframe直接直接在页面嵌套iframe标签指定src就可以了。
<iframe src="demo_iframe.html"></iframe>
可以通过iframe嵌套通用的页面, 提高代码的重用率, 比如页面的头部样式和底部版权信息
Frame切换
在使用selenium打开一个网页时,我们的操作范围默认是当前的 html ,并不包含被嵌入的html文档里面的内容。如果我们要操作被嵌入的 html 文档 中的元素, 就必须把操作范围切换到被嵌入的文档中。
WebDriver对象的switch_to属性转换,形如
//其中switchFlag可以是frame元素的name或者 ID属性及 frame 所对应的 WebElement 对象。
driver.switchTo().frame(switchFlag);
例如frame元素的 id 为‘frame1’,切换语句为:driver.switch_to.frame('frame1')
例如frame元素的name属性值为‘innerFrame’ ,切换语句为:driver.switch_to.frame('innerFrame')
为什么要切换frame表单
参数可以是id,name或者能定位到frame的元素。推荐使用name
在切换其他frame页面之前,需要将WebDriver 对象切换回默认区域:
webDriver.switchTo().defaultContent();
通常采用id和name就能够解决绝大多数问题。但有时候frame并无这两项属性,则可以用index和WebElement来定位:
- index从0开始,传入整型参数即判定为用index定位,传入str参数则判定为用id/name定位
- WebElement对象,即用find_element系列方法所取得的对象,我们可以用tag_name、xpath等来定位frame对象
多层嵌套frame
frame需层层切!
有时候我们会遇到嵌套的frame,如下:
<html>
<iframe id="frame1">
<iframe id="frame2" / >
</iframe>
</html>
从主文档切到frame2,一层层切进去
driver.switch_to.frame("frame1")
driver.switch_to.frame("frame2")
从frame2再切回frame1,这里selenium给我们提供了一个方法能够从子frame切回到父frame,而不用我们切回主文档再切进来
driver.switch_to.parent_frame() # 如果当前已是主文档,则无效果
-
如果需要操作多个嵌套的iframe,需要逐层进入。例如,先进入最外层的iframe,然后进入内部的iframe。
-
完成操作后,可以使用
switch_to_parent_frame()
或switch_to_default_content()
回到上一级或最外层的页面。
在处理iframe时,需要特别注意iframe的加载状态,确保在尝试访问iframe中的元素之前,iframe已经完全加载完成。
安居客登录
登录 (anjuke.com)
如下,红色区域部分是一个<iframe>标签
frame嵌套页面再比如:优酷登录窗口
弹窗
alert弹框
警告消息框 alert 方法有一个参数,即希望对用户显示的文本字符串。该字符串不是 HTML 格式。该消息框提供了一个“确定”按钮让用户关闭该消息框,并且该消息框是模式对话框,也就是说,用户必须先关闭该消息框然后才能继续进行操作。
selenium处理alert() 提示框:
- driver.switchTo().alert(); 获取alert
- alert.accept(); 点确定
- alert.dismiss(); 点取消
- alert.getText();获取alert的内容
confirm弹框
确认消息框 使用确认消息框可向用户问一个“是-或-否”问题,并且用户可以选择单击“确定”按钮或者单击“取消”按钮。confirm 方法的返回值为 true 或 false。该消息框也是模式对话框:用户必须在响应该对话框(单击一个按钮)将其关闭后,才能进行下一步操作。
1
div弹窗
div弹窗是浏览器中比较好定位的弹窗,定位的方法与普通的元素一样。不过这里会有一个坑,明明可以找到这个按钮,但是就是定位不到。这个就是因为当前有div弹窗弹出的时候,需要设置一下等待时间,等页面元素加载完毕,再去做其他操作。这里用百度登陆为例子:
元素等待
强制等待
强制等待:sleep
sleep,设置等待多长时间,就要等待多长时间。等待完成后,才会继续下一步:
//设置等待时间,单位是秒 sleep(3)
由于web加载的速度取决于测试的硬件、网速、服务器的响应时间等因素。如果时间设置太长,容易造成时间浪费,如果设置太短又可能会造成在web还没有加载完所需要定位的element,而出现报错。由于等待时间无法确定,使用太多的sleep会影响运行速度,大大地降低效率。
隐式等待
隐式等待:implicitlyWait
采用implicitly_wait()方法来设置等待时间,这种方法要比time.sleep更智能一些。
使用implicitlyWait方法设定查找页面元素的最大等待时间,调用findElement方法时
没有立刻找到定位元素,则程序会每间隔一段时间就尝试判断页面的D0M中是否出现被查找元素,若超过设定的等待时长依旧没有找到,则抛出NoSuchElementException//只需要设置一次,所有的元素都可有最多 10s 的等待加载的时间 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); WebElement element = driver.findElement(By.id("exampleId"));
隐式等待默认设置等待时间为0,同时隐式等待是对driver起作用,所以只要设置一次即可,不需要到处设置。
隐式等待原理:
在每次进行 find_element时起作用,implicitlyWait()会将一个超时的时间阀值传递给 WebDriver,在findelement或者findelements的时候,首先去找 web element,如果没有找到,判断时间否超超过 implicitlyWait()传递进来的阀值,如果没有超过,则再次找这个element,直到找到 element 或者时间超过最大阀值。
显式等待
显式等待:使用ExpectedConditions类中自带方法, 可以进行显试等待的判断。
WebDriverWait(driver,10,1) 在等待期间,每隔1s一定时间,调用until或until_not里的方法,直到它返回True或False.
- driver:浏览器驱动。
- 10:最长超时时间,默认以秒为单位。
- 1:检测的的间隔(步长) 时间,默认为 0.5s。
显式等待能自定义等待条件,只要满足等待条件即可执行下一步代码操作,一般需要配合该类的until()和until_not()方法一起用.
表示程序每隔一定时间就检查一遍条件是否成立,如果成立了就执行下一步,否则就继续等。直到超过设置的最长时间,然后抛出超时错误TimeoutException
//判断某元素是否可访问并且可启用,比如能够点击 new WebDriverWait(driver, 10) .until(ExpectedConditions.elementToBeClickable(webElement)); //判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0 new WebDriverWait(driver, 10) .until(ExpectedConditions.visibilityOf(webElement)); //判断某元素否被选中 new WebDriverWait(driver, 10) .until(ExpectedConditions.elementToBeSelected(webElement));
常用的显示等待条件如下:
自定义显示等待
注意ExpectedConditions的写法变成了自定义
WebDriverWait wait = new WebDriverWait(driver, Manager_Config.getCmdTimeout() / 1000);
try {
Alert alert = wait.until(new ExpectedCondition<Alert>() {
@Override
public Alert apply(WebDriver driver) {
try {
return driver.switchTo().alert();
} catch (NoAlertPresentException e) {
return null;
}
}
});
if (alert != null)
alert.accept();
执行js
执行js脚本
executeScript是同步方法,用它执行js代码会阻塞主线程执行,直到js代码执行完毕;
import org.openqa.selenium.JavascriptExecutor;
//第一行代码将driver强制转换为JavascriptExecutor
JavascriptExecutor js = (JavascriptExecutor) driver;
//第二行代码是执行js,参数script是要执行的js语句,第二个参数对于executeScript这个方法,取决于js语句是否需要参数。
js.executeScript(String script, object... args);
executeScript方法返回值Boolean, Long, String, List or WebElement. 或者是 null.
- 如果返回一个页面元素(document element), 这个方法就会返回一个WebElement
- 如果返回浮点数字,这个方法就返回一个double类型的数字
- 返回非浮点数字,方法返回Long类型数字
- 返回boolean类型,方法返回Boolean类型
- 如果返回一个数组,方法会返回一个List
- 其他情况,返回一个字符串
- 如果没有返回值,此方法就会返回null
应用举例:用js弹出alert
JavascriptExecutor js = (JavascriptExecutor) webDriver;
js.executeScript("alert('Test Case Execution Is started Now..')");
webDriver.switchTo().alert().accept();
有些情况下,selenium提供的API无法完成对应的操作或者操作比较麻烦,此时可以借助JS脚本来实现,例如执行滑动滚动条。
js ='window.scrollTo(0,100)' # 要执行的JS脚本语句
driver.execute_script(js) # 执行JS脚本
Edge驱动下载
Edge驱动下载:Microsoft Edge - Webdriver (windows.net)
Firefox驱动:https://github.com/mozilla/geckodriver/releases/
.Firefox驱动名称为geckodriver