三. Selenium 常用 API
✅3.1 定位元素
对象的定位应该是自动化测试的核心,要想操作一个对象,首先应该识别这个对象;
Selenium提供了8种定位方式。
- id
- name
- class name
- tag name
- link text
- partial link text
- xpath
- css selector
这8种定位方式在Java selenium中所对应的方法为:
- findElement(By.id())
- findElement(By.name())
- findElement(By.className())
- findElement(By.tagName())
- findElement(By.linkText())
- findElement(By.partialLinkText())
- findElement(By.xpath())
- findElement(By.cssSelector())
我们可以通过借助浏览器的开发者工具,去获取我们想要去定位元素的值,假设我们要对百度页面的输入框进行测试,我们可以点击点击输入框打开开发者工具,去获取我们要的值,这里代码给大家演示:
public static void main(String[] args) { // 谷歌驱动 ChromeOptions options = new ChromeOptions(); // 允许所有请求 options.addArguments("--remote-allow-origins=*"); WebDriver webDriver = new ChromeDriver(options); // 启动需要打开的网页 webDriver.get("https://www.baidu.com"); // 通过id来定位,在输入框输入你好 webDriver.findElement(By.id("kw")).sendKeys("你好"); // 通过name来定位 webDriver.findElement(By.name("wd")).sendKeys("你好"); // 通过Xpath来定位 webDriver.findElement(By.xpath("//*[@id=\"kw\"]")).sendKeys("你好"); // 通过css选择器来定位 webDriver.findElement(By.cssSelector("#kw")).sendKeys("你好"); }
这里我们就是通过定位到输入框的元素,然后在输入框内输入你好字段;
✅3.2 操作对象
webdriver 中比较常用的操作对象的方法有下面几个:
- click 点击对象
- send_keys 在对象上模拟按键输入
- clear 清除对象输入的文本内容
- submit 提交
- text 用于获取元素的文本信息
private static void test2() throws InterruptedException { // 谷歌驱动 ChromeOptions options = new ChromeOptions(); // 允许所有请求 options.addArguments("--remote-allow-origins=*"); WebDriver webDriver = new ChromeDriver(options); // 启动需要打开的网页 webDriver.get("https://www.baidu.com"); // 利用类选择器定位元素,百度输入框 WebElement element = webDriver.findElement(By.cssSelector("#kw")); // 利用Xpath路径去定位元素 //WebElement element = webDriver.findElement(By.xpath("//*[@id=\"kw\"]")); element.sendKeys("你好"); sleep(2000); // 输入内容进行点击 webDriver.findElement(By.cssSelector("#su")).click(); sleep(2000); }
这里就是通过代码在输入框里输入你好,然后点击百度一下的按钮,实现的一个自动化操作过程;
这里需要注意的是click 和 submit 的区别:
- 如果点击的元素放在form标签中,此时使用submit实现的效果和click是一样的;
- 如果点击的元素放在form标签外,此时使用submit就会摆错;
✅3.3 添加等待
1)sleep休眠
添加休眠非常简单,我们需要引入time 包,就可以在脚本中自由的添加休眠时间了,这里的休眠指固定休眠;
2)隐式等待
通过添加driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS)的方法去添加隐式等待,通过隐式等待,WebDriver在试图查找_任何_元素时在一定时间内轮询DOM。当网页上的某些元素不是立即可用并且需要一些时间来加载时是很有用的,这块比较抽象,可以参考一下官方文档:
等待 | Selenium
https://www.selenium.dev/zh-cn/documentation/webdriver/waits/
✅3.4 打印信息
不管是在做功能测试还是自动化测试,最后一步需要拿实际结果与预期进行比较。这个比较的称之为断言。 我们通常可以通过获取title 、URL和text等信息进行断言。text方法在前面已经讲过,它用于获取标签对之间的文本信息。
- getTitle(): 用于获得当前页面的title。
- getCurrentUrl() : 用户获得当前页面的URL。
- getText() 获取页面文本信息。
这里我们打印url和title来展示一下:
private static void test3() { // 谷歌驱动 ChromeOptions options = new ChromeOptions(); // 允许所有请求 options.addArguments("--remote-allow-origins=*"); WebDriver webDriver = new ChromeDriver(options); // 启动需要打开的网页 webDriver.get("https://www.baidu.com/"); // 获取当前页面的url String url = webDriver.getCurrentUrl(); // 获取当前页面的title String title = webDriver.getTitle(); // 通过对比,来判断是否相同 if(url.equals("https://www.baidu.com/") && title.equals("百度一下,你就知道")){ System.out.println("测试通过"); }else { System.out.println("测试未通过"); } }
当然这里不止这两个方法,还有别的方法可以获取到别的属性,可以去官方文档自行查看;
✅3.5 浏览器操作
在使用浏览器浏览网页时,浏览器提供了后退和前进按钮,可以方便地在浏览过的网页之间切换,WebDriver也提供了对应的back()和forward()方法来模拟后退和前进按钮。下面通过例子来演示这两个方法的使用。
- back() 模拟浏览器后退按钮
- forward() 模拟浏览器前进按钮
- refresh() 刷新页面(F5)
private static void test4() throws InterruptedException { //创建谷歌驱动 ChromeOptions options = new ChromeOptions(); // 允许所有请求 options.addArguments("--remote-allow-origins=*"); WebDriver webDriver = new ChromeDriver(options); // 打开百度首页 webDriver.get("https://www.baidu.com/"); // 搜索520 webDriver.findElement(By.cssSelector("#kw")).sendKeys("你好"); // 点击 webDriver.findElement(By.cssSelector("#su")).click(); // 浏览器后退 sleep(2000); webDriver.navigate().back(); // 浏览器刷新 sleep(2000); webDriver.navigate().refresh(); // 浏览器前进 sleep(2000); webDriver.navigate().forward(); }
有时候我们希望能以某种浏览器尺寸找开,访问的页面在这种尺寸下运行。例如可以将浏览器设置成移动端大小(480* 800),然后访问移动站点,对其样式进行评估;WebDriver 提供了 manage().window().setSize()方法来设置浏览器的大小。
- maximize() 设置浏览器最大化
- setSize() 设置浏览器宽高
private static void test5() throws InterruptedException { //创建谷歌驱动 ChromeOptions options = new ChromeOptions(); // 允许所有请求 options.addArguments("--remote-allow-origins=*"); WebDriver webDriver = new ChromeDriver(options); // 打开百度首页 webDriver.get("https://www.baidu.com/"); // 搜索520 webDriver.findElement(By.cssSelector("#kw")).sendKeys("你好"); sleep(2000); // 点击 webDriver.findElement(By.cssSelector("#su")).click(); sleep(2000); // 浏览器显示最大化 webDriver.manage().window().maximize(); sleep(2000); // 浏览器全屏 webDriver.manage().window().fullscreen(); sleep(2000); // 按照指定大小来显示 webDriver.manage().window().setSize(new Dimension(600,800)); }
✅3.6 键盘操作
Keys()类提供了键盘上几乎所有按键的方法。 前面了解到, sendKeys()方法可以用来模拟键盘输入, 除此之 外, 我们还可以用它来输入键盘上的按键, 甚至是组合键, 如 Ctrl+A、 Ctrl+C 等;
以下为常用的键盘操作:
sendKeys(Keys.BACK_SPACE) 回格键(BackSpace)
sendKeys(Keys.SPACE) 空格键 (Space)
sendKeys(Keys.TAB) 制表键 (Tab)
sendKeys(Keys.ESCAPE) 回退键(Esc)
sendKeys(Keys.ENTER) 回车键(Enter)
sendKeys(Keys.CONTROL,‘a’) 全选(Ctrl+A)
sendKeys(Keys.CONTROL,‘c’) 复制(Ctrl+C)
sendKeys(Keys.CONTROL,‘x’) 剪切(Ctrl+X)
sendKeys(Keys.CONTROL,‘v’) 粘贴(Ctrl+V)
private static void test6() throws InterruptedException { //谷歌驱动 ChromeOptions options = new ChromeOptions(); // 允许所有请求 options.addArguments("--remote-allow-origins=*"); WebDriver webDriver = new ChromeDriver(options); webDriver.get("https://www.baidu.com"); // 搜索520 webDriver.findElement(By.cssSelector("#kw")).sendKeys("你好"); // 测试Ctrl+A sleep(2000); webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL, "A"); // 测试Ctrl+X sleep(2000); webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL, "X"); // 测试Ctrl+V sleep(2000); webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL, "V"); // 点击 sleep(2000); webDriver.findElement(By.cssSelector("#su")).click(); }
✅3.7 鼠标操作
通过前面例子了解到,可以使用click()来模拟鼠标的单击操作,现在的Web产品中提供了更丰富的鼠标交互方式, 例如鼠标右击、双击、悬停、甚至是鼠标拖动等功能。在WebDriver中,将这些关于鼠标操作的方法封装在ActionChains类提供。 Actions 类提供了鼠标操作的常用方法:
- contextClick() 右击
- clickAndHold() 鼠标点击并控制
- doubleClick() 双击
- dragAndDrop() 拖动
- release() 释放鼠标
- perform() 执行所有Actions中存储的行为
private static void test7() throws InterruptedException { //谷歌驱动 ChromeOptions options = new ChromeOptions(); // 允许所有请求 options.addArguments("--remote-allow-origins=*"); WebDriver webDriver = new ChromeDriver(options); webDriver.get("https://www.baidu.com/"); // 搜索框输入520 webDriver.findElement(By.cssSelector("#kw")).sendKeys("520"); // 点击百度一下按钮 webDriver.findElement(By.cssSelector("#su")).click(); sleep(2000); //找到测试鼠标右键点击"网页" WebElement webElement = webDriver.findElement(By.cssSelector("#s_tab > div > b")); // 鼠标右击 Actions actions = new Actions(webDriver); sleep(2000); actions.moveToElement(webElement).contextClick().perform(); }
✅3.8 定位一组元素
webdriver 可以很方便的使用findElement 方法来定位某个特定的对象,不过有时候我们却需要定位一组对象,这时候就需要使用findElements 方法;定位一组对象一般用于以下场景:
- 批量操作对象,比如将页面上所有的checkbox 都勾上
- 先获取一组对象,再在这组对象中过滤出需要具体定位的一些对象。比如定位出页面上所有的checkbox,然后选择最后一个
以下是个简单页面:
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> </head> <body> <fieldset> <legend>单选按钮radio</legend> <form action=""> <label for=""><input type="radio" name="fruit" value="pg" id="pg">苹果</label> <label for=""><input type="radio" name="fruit" value="jz" id="jz">橘子</label> <label for=""><input type="radio" name="fruit" value="xj" id="xj">香蕉</label> <label for=""><input type="radio" name="fruit" value="li" id="li" checked="">梨</label> <label for=""><input type="radio" name="fruit" value="xg" id="xg" disabled="" >西瓜</label> </form> </fieldset> <br> <fieldset> <legend>多选按钮checkbox</legend> <form action=""> <input type="checkbox" name="checkbox" value="汽车" id="qc">汽车<br> <input type="checkbox" name="checkbox" value="购物" id="gw">购物<br> <input type="checkbox" name="checkbox" value="旅游" id="ly" readonly="">旅游 <br> <input type="checkbox" name="checkbox" value="音乐" id="yy" disabled="">音乐 <br> </form> </fieldset> </body> </html>
private static void test8() { //谷歌驱动 ChromeOptions options = new ChromeOptions(); // 允许所有请求 options.addArguments("--remote-allow-origins=*"); WebDriver webDriver = new ChromeDriver(options); webDriver.get("http://127.0.0.1:8080/aaa/test.html"); //定位input标签,并将其扔到List集合中 List<WebElement> webElements = webDriver.findElements(By.cssSelector("input")); // 如果元素的type值等于checkbox就进行点击 for (int i = 0; i < webElements.size(); i++) { // getAttribute是获取当前页面元素的属性值,type是当前元素的属性 if(webElements.get(i).getAttribute("type").equals("checkbox")){ webElements.get(i).click(); }else { ; } } }
通过动态图可以发现,这样就实现了一个 多选的操作;
✅3.9 下拉框处理
下拉框是我们最常见的一种页面元素,对于一般的元素,我们只需要一次就定位,但下拉框里的内容需要进行两次定位,先定位到下拉框对下拉框进行操作后,再定位到下拉框内里的选项;
/
private static void test9() { //谷歌驱动 ChromeOptions options = new ChromeOptions(); // 允许所有请求 options.addArguments("--remote-allow-origins=*"); WebDriver webDriver = new ChromeDriver(options); webDriver.get("http://127.0.0.1:8080/aaa/test2.html"); WebElement webElement = webDriver.findElement(By.cssSelector("#ShippingMethod")); Select select = new Select(webElement); // 下标是从0开始计数的 select.selectByIndex(2); }
✅3.10 切换窗口句柄
在页面操作过程中有时候点击某个链接会弹出新的窗口, 这时就需要主机切换到新打开的窗口上进行操作。WebDriver提供了switchTo().window()方法可以实现在不同的窗口之间切换。 以百度首页和百度注册页为例,在两个窗口之间的切换。
private static void test10() { //谷歌驱动 ChromeOptions options = new ChromeOptions(); // 允许所有请求 options.addArguments("--remote-allow-origins=*"); WebDriver webDriver = new ChromeDriver(options); webDriver.get("https://www.baidu.com/"); // 点击百度页面的新闻按钮 webDriver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click(); // getWindowHandles获取所以得窗口句柄 // getWindowHandles获取当前页面的窗口句柄 // 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); webDriver.findElement(By.cssSelector("#ww")).sendKeys("你好"); webDriver.findElement(By.cssSelector("#s_btn_wr")).click(); }
这是一个在第二个页面的输入框内搜索内容,如果不调用webDriver.getWindowHandle()方法的话,代码就会报错;
自动化测试中经常有点击一个链接,打开新的窗口。人为操作的话,可以通过眼睛看,识别不同的窗口点击切换。但是是自动化脚本没长眼睛,它不知道你要操作哪个窗口,这时候只能句柄来判断了。
浏览器窗口的属性用句柄(handle)来识别。窗口句柄是窗口的唯一标识,可看做窗口的身份证号。
✅3.11 截图操作
自动化用例是由程序去执行,因此有时候打印的错误信息并不十分明确。如果在脚本执行出错的时候能对当前窗口截图保存,那么通过图片就可以非常直观地看出出错的原因。 WebDriver提供了截图函数getScreenshotAs()来截取当前窗口;
private static void test11() throws IOException, InterruptedException { //谷歌驱动 ChromeOptions options = new ChromeOptions(); // 允许所有请求 options.addArguments("--remote-allow-origins=*"); WebDriver webDriver = new ChromeDriver(options); webDriver.get("https://www.baidu.com/"); webDriver.findElement(By.cssSelector("#kw")).sendKeys("软件测试"); webDriver.findElement(By.cssSelector("#su")).click(); sleep(2000); File file = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); // 放到指定路径下 FileUtils.copyFile(file,new File("D://20230527jietu.png")); }
✅3.12 上传文件操作
对于通过input标签实现的上传功能,可以将其看作是一个输入框,即通过sendKeys()指定本地文件路径的方式实现文件上传;
private static void test12() { //谷歌驱动 ChromeOptions options = new ChromeOptions(); // 允许所有请求 options.addArguments("--remote-allow-origins=*"); WebDriver webDriver = new ChromeDriver(options); webDriver.get("http://127.0.0.1:8080/aaa/bbb.html"); // sendKeys里是上传文件的路径 webDriver.findElement(By.cssSelector("input")).sendKeys("D:\\Bin\\xnn_res"); }
✅面试题:quit 和 close的区别
- quit 关闭了整个浏览器,close只是关闭了当前的页面;
- quit会清空缓存,close则不会;
觉得有帮助的小伙伴可以一键三连,蟹蟹~~