Selenium Web自动化测试工具
之前写过一篇关于自动化测试的博客,里面是有的chrome驱动,由于不适配缘故,更新以下Edge驱动。 自动化测试
Selenium环境部署
- 准备 Edge 浏览器
- 准备 Edge 驱动包 a .查看自己的Edge浏览器版本(浏览器版本和驱动版本一定要对应) b .下载对应的驱动包,下载路径:https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/![在这里插入图片描述](https://img-blog.csdnimg.cn/b5116477254440069866148e00026d74.png)![在这里插入图片描述](https://img-blog.csdnimg.cn/3e26a1480c6a47e580d2261cedfdd470.png) c .解压下载好的 驱动包,找到
msedgedriver.exe
,将其放在 Java 系统环境变量下。 - 准备 selenium 工具包
<dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.8.0</version></dependency>
- 准备Java8及以上环境
Selenium - 驱动 - 浏览器 三者的关系
我们可以启动以下驱动,可以看到驱动绑定的端口:
127.0.0.1:9515
编写一个简单的自动化测试用例
- 创建 maven 项目
- 导入 selenium 依赖
- 在
test/java/com
下自定义一个包 - 编写代码 自动化测试类:
importorg.openqa.selenium.By;importorg.openqa.selenium.chrome.ChromeDriver;/**
* @author SunYuHang
*/publicclassAutoTest{//打开我自己发布的博客网站 登录博客网站 publicvoidTest()throwsInterruptedException{EdgeOptions options =newEdgeOptions();
options.addArguments("--remote-allow-origins=*");EdgeDriver driver =newEdgeDriver(options);
driver.navigate().to("http://43.140.252.242:9090/login.html");// driver.get("http://43.140.252.242:9090/login.html");
driver.findElement(By.cssSelector("#username")).sendKeys("admin");Thread.sleep(5000);
driver.findElement(By.cssSelector("#password")).sendKeys("admin");Thread.sleep(5000);
driver.findElement(By.cssSelector("#submit")).click();Thread.sleep(5000);
driver.quit();}}
运行测试类的主类:
publicclassRunAutoTest{publicstaticvoidmain(String[] args)throwsInterruptedException{AutoTest autoTest =newAutoTest();autoTest.Test();}}
QQ录屏20230409160030
这个代码运行起来就会在我的博客系统页面实现自动登录。
简单自动化示例主要包含5个步骤
- 创建驱动示例,创建会话
- 访问网站
- 查找元素
- 操作元素
- 结束会话
Selenium 基础方法
Selenium 常见的元素操作
1.查找页面元素
findElement()
参数:By类(通过什么方式来查找元素,例如xpath)
返回值:webElement
- 当元素可以在页面中找到,程序正确退出
- 当元素在页面中找不到时,程序执行报错
findElements()
参数:By类 (通过什么方式来查找元素)
返回值:List< WebElement >
2.元素定位的方式-By类
元素定位的方式(By 类后面跟的内容),主要分为两种:selector和xpath
selector 又分为 基础选择器和复合选择器
此处用
cssSelector
来举例
By.cssSelector("页面元素")
选择元素的步骤:
打开浏览器,F12打开开发者工具,然后选择元素
然后将 copy 的粘贴在
By.cssSelector("")
的引号里面即可。
xpath语法
层级: /代表子集, //代表跳级
属性:@
函数:contains()等
还是按照上面的步骤,我们给大家复制一段xpath来看看。
复制XPath:
//*[@id="su"]
复制完整的XPath:
/html/body/div[1]/div[2]/div[5]/div[1]/div/form/span[2]/input
完整的就是找寻 html 标签下紧邻的 body 标签下紧邻的第一个 div 下紧邻的…的 input 标签。
不完整的就是 跳着找到 id="su"的元素
【拓展】那么我们为什么要了解xpath的语法呢?
因为自动化测试要求元素必须要唯一。但是手动在页面复制的selector或者xpath并不一定唯一,需要我们手动的进行小范围的修改。
【拓展】那么我们如何确定一个xpath在页面中是否唯一呢?
- F12打开开发者工具
- Ctrl+f就会弹出一个搜索框,如果显示1,则表示唯一,反之不唯一.
3.输入文本 sendKeys
仅适用与文本字段和内容可编辑的元素(用于其他元素也不会报错)
两种方式:
//方式一WebElement ele = driver.findElement(By.cssSelector("#kw"));
ele.sendKeys("孙宇航");//方式二
driver.findElement(By.cssSelector("#kw")).sendKeys("孙宇航");
4.点击 click
用于点击一个按钮
driver.findElement(By.cssSelector("#su")).click();
5.提交 submit
submit 相当于通过回车键提交,但是 selenium 官方不推荐使用 submit,更推荐 click。因为 submit 仅适用于表单元素,而且能使用 submit 提交,就一定能使用 click 代替,而反过来不行。
6.清除 clear
使用场景不多,适用于频繁的测试输入是否可以重复输入
driver.findElement(By.cssSelector("#kw")).sendKeys("孙宇航");
driver.findElement(By.cssSelector("#kw")).clear();
driver.findElement(By.cssSelector("#kw")).sendKeys("张美莹");
driver.findElement(By.cssSelector("#kw")).clear();
7. 获取文本 getText
publicvoidbaseController(){EdgeDriver driver =newEdgeDriver();
driver.get("https://www.baidu.com");// 获取文本, 能正常获取到String text = driver.findElement(By.cssSelector("#hotsearch-content-wrapper > li:nth-child(1) > a > span.title-content-title")).getText();System.out.println("获取文本的结果 : "+ text);// 获取属性对应的值, 不能获取到String value = driver.findElement(By.cssSelector("#su")).getText();System.out.println("获取属性对应的值的结果 : "+ value);
driver.quit();}
运行结果:
8.获取属性对应的值 getAttribute
System.out.println(driver.findElement(By.cssSelector("#su")).getAttribute("type"));System.out.println(driver.findElement(By.cssSelector("#su")).getAttribute("id"));System.out.println(driver.findElement(By.cssSelector("#su")).getAttribute("value"));System.out.println(driver.findElement(By.cssSelector("#su")).getAttribute("class"));
运行结果:
9. 获取页面标题和URL
获取标题:
driver.getTitle()
获取URL:
driver.getCurrentUrl()
窗口控制
1. 窗口大小的设置
最大化,最小化,全屏窗口,手动设置窗口大小
EdgeDriver driver =newEdgeDriver();Thread.sleep(3000);// 窗口最大化
driver.manage().window().maximize();Thread.sleep(3000);// 窗口最小化
driver.manage().window().minimize();Thread.sleep(3000);// 全屏
driver.manage().window().fullscreen();Thread.sleep(3000);// 手动设置窗口大小
driver.manage().window().setSize(newDimension(1024,768));Thread.sleep(3000);// 关闭
driver.quit();
2. 窗口的切换
EdgeDriver driver =newEdgeDriver();// 去到百度首页
driver.get("https://www.baidu.com");// 点击百度上面的图片
driver.findElement(By.cssSelector("#s-top-left > a:nth-child(6)")).click();Thread.sleep(2000);// 获取图片页的 "百度一下" 按钮
driver.findElement(By.cssSelector("#homeSearchForm > span.s_btn_wr > input"));Thread.sleep(2000);
driver.quit();
运行结果:发现百度按钮找不到
报错原因:
当浏览器每次打开一个标签页的时候,会自动的给一个标签进行标识,这个标识我们称之为“句柄”,如果直接获取,浏览器就不知道是获取哪个页面的百度一下按钮了。
测试一下:
EdgeDriver driver =newEdgeDriver();
driver.get("https://www.baidu.com");
driver.findElement(By.cssSelector("#s-top-left > a:nth-child(6)")).click();// 获取当前页面的句柄String curHandle = driver.getWindowHandle();System.out.println("当前句柄 : "+curHandle);// 获取所有页面的句柄Set<String> handles = driver.getWindowHandles();for(String handle : handles){System.out.println(handle);}
那么我们想要获取图片页面的百度一下按钮,该怎么办呢?
EdgeDriver driver =newEdgeDriver();
driver.get("https://www.baidu.com");
driver.findElement(By.cssSelector("#s-top-left > a:nth-child(6)")).click();// 获取当前页面的句柄String curHandle = driver.getWindowHandle();System.out.println("当前句柄 : "+curHandle);Set<String> handles = driver.getWindowHandles();for(String handle : handles){// 如果不是当前页面的句柄, 就切换窗口if(handle != curHandle){
driver.switchTo().window(handle);}}Thread.sleep(2000);// 获取图片页面百度一下按钮
driver.findElement(By.cssSelector("#homeSearchForm > span.s_btn_wr > input"));Thread.sleep(2000);
driver.quit();
如果打开好几个窗口,我们怎么切换呢?
driver.get();
3. 屏幕截图
先要导入 保存屏幕截图的依赖
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency>
代码示例:去到百度首页,输入孙宇航回车,然后获取新页面的孙宇航元素。
EdgeDriver driver =newEdgeDriver();
driver.get("https://www.baidu.com");
driver.findElement(By.cssSelector("#kw")).sendKeys("孙宇航");
driver.findElement(By.cssSelector("#su")).click();// 获取新打开页面的元素
driver.findElement(By.cssSelector("#\31 > div > h3 > a"));// 退出
driver.quit();
运行报错,找不到元素。
为什么会找不到元素呢?
修改代码,在查找元素之前保存一下跳转后的页面截图
EdgeDriver driver =newEdgeDriver();
driver.get("https://www.baidu.com");
driver.findElement(By.cssSelector("#kw")).sendKeys("孙宇航");
driver.findElement(By.cssSelector("#su")).click();// 屏幕截图 (保存现场)File srcFile = driver.getScreenshotAs(OutputType.FILE);String filename ="my.png";FileUtils.copyFile(srcFile,newFile(filename));// 获取新打开页面的元素
driver.findElement(By.cssSelector("#\31 > div > h3 > a"));// 退出
driver.quit();
查看my.png:我们可以发现找不到元素的原因是页面还没来得及渲染。由此我们可以知道程序执行的速度远远大于页面渲染速度。
要是想正常获取页面元素,就需要加入等待机制。(在保存屏幕之前,等待3-5秒)
等待
为什么要等待呢?目的就是为了解决程序执行速度比浏览器渲染速度要快的问题。
我们要学习的等待有四种:
- 强制等待
- 隐式等待
- 显式等待
- 流畅等待
1. 强制等待
Thread.sleep();
程序阻塞进行,会用到,但是自动化里面用到的不是很多。
每一个自动化测试方法就是一个自动化测试用例,而每个测试用例只能接受十几秒或者几分钟之内的等待。
2. 隐式等待
针对屏幕截图遇到的问题,添加隐式等待,就可以正常获取页面元素了。
EdgeDriver driver =newEdgeDriver();// 添加隐式等待
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
driver.get("https://www.baidu.com");
driver.findElement(By.cssSelector("#kw")).sendKeys("孙宇航");
driver.findElement(By.cssSelector("#su")).click();// 获取新打开页面的元素
driver.findElement(By.cssSelector("#\31 > div > h3 > a"));// 退出
driver.quit();
隐式等待会作用于 driver 的整个生命周期。虽然代码写在前面,但是隐式等待会一直轮询判断元素是否存在,如果元素存在,并且在1ms就找到了,就不会等待三秒,直接往下执行,如果不存在,就会按照设置的时间里轮询等待。时间一过,如果还没查到,程序就会报错。
3. 显式等待
使用显式等待解决的问题
privateEdgeDriver driver =newEdgeDriver();publicvoidwindowController()throwsInterruptedException,IOException{
driver.get("https://www.baidu.com");
driver.findElement(By.cssSelector("#kw")).sendKeys("孙宇航");
driver.findElement(By.cssSelector("#su")).click();// 添加显示等待newWebDriverWait(driver,Duration.ofSeconds(5)).until(driver->driver.findElement(By.cssSelector("#\31 > div > h3 > a")));
driver.quit();}
【拓展】
- 隐式等待和强制等待不能同时使用,同时使用可能会出现不一样的等待结果
- 有时候隐式等待和显式等待不生效时,可以使用强制等待。
浏览器导航
浏览器的前进、后退、刷新操作
privateEdgeDriver driver =newEdgeDriver();publicvoidnavigateController()throwsInterruptedException,IOException{// 请求百度首页的写法是简写//driver.get("https://www.baidu.com");
driver.navigate().to("https//www.baidu.com");Thread.sleep(3000);// 回退
driver.navigate().back();Thread.sleep(3000);// 前进
driver.navigate().forward();Thread.sleep(3000);// 刷新
driver.navigate().refresh();Thread.sleep(3000);
driver.quit();}
弹窗
弹窗基本有三种: 警告弹窗,确认弹窗,提示弹窗
1. 警告弹窗
2. 确认弹窗
3. 提示弹窗
处理弹窗的步骤:
- 将 driver 对象作用到弹窗上(切换到弹窗)
- 点击确认/点击取消/提示弹窗输入文本,再确认/取消
privateEdgeDriver driver =newEdgeDriver();publicvoidalertController()throwsInterruptedException{// 本地打开 html 文件后, 需要复制浏览器的 url 到 get 里, 而不是本地文件的路径
driver.get("文件路径/selenium-html/Prompt.html");Thread.sleep(3000);// 打开弹窗
driver.findElement(By.cssSelector("body > input[type=button]")).click();Thread.sleep(3000);// 切换到弹窗进行弹窗的处理Alert alert = driver.switchTo().alert();Thread.sleep(3000);// 弹窗输入文本
alert.sendKeys("abcdef~");// 点击确认
alert.accept();// 点击取消//alert.dismiss();
driver.quit();}
- 警告弹窗中, 切换到弹窗,调用
accept()
- 确认弹窗中, 切换到弹窗,调用
accept()
或者dismiss()
- 提示弹窗中, 切换到弹窗, 可以先输入文本, 调用
sendKeys()
, 然后调用accept()
或者dismiss()
. 提示:这里的sendKeys()
在页面上看不到输入文本的执行效果虽然警告弹窗只有确认按钮, 但是 accept 和 dismiss 都能处理. 虽然警告弹窗和确认弹窗都没有输入文本的地方, 但如果要执行 alert.sendKKeys(), 代码也不会报错.
选择框
选择的方式:根据文本来选择、根据属性值来选择、根据序号来选择
publicvoidselectController()throwsInterruptedException{
driver.get("文件路径/selenium-html/select.html");Thread.sleep(3000);WebElement ele = driver.findElement(By.cssSelector("#ShippingMethod"));// 先创建选择框对象Select select =newSelect(ele);// 根据文本来选择// select.selectByVisibleText("UPS Next Day Air ==> $12.51");// 根据属性值来选择// select.selectByValue("12.51");// 根据序号来选择 (序号从 0 开始)
select.selectByIndex(1);Thread.sleep(3000);
driver.quit();}
执行脚本
主要方法:
executeScript()
参数:js代码
页面置顶
publicvoidscriptController()throwsInterruptedException{
driver.get("https://image.baidu.com/");Thread.sleep(3000);// 执行 js 命令: 让页面置顶/置底
driver.executeScript("document.documentElement.scrollTop=500");Thread.sleep(3000);// 0 就是顶部
driver.executeScript("document.documentElement.scrollTop=0");Thread.sleep(3000);
driver.quit();}
拓展:
driver.get("https://www.baidu.com/");Thread.sleep(3000);// 执行 js 命令
driver.executeScript("var texts = document.querySelector('#kw'); texts.value = 'abcdef'");Thread.sleep(3000);
driver.quit();
文件上传
publicvoidfileUploadController()throwsInterruptedException{
driver.get("文件路径/selenium-html/upload.html");Thread.sleep(3000);// 文件上传
driver.findElement(By.cssSelector("body > div > div > input[type=file]")).sendKeys("文件路径\\selenium-html\\upload.html");Thread.sleep(3000);
driver.quit();}
浏览器的参数设置
selenium 自动化测试, 它的行为是打开浏览器, 然后再去访问链接, 然后再对页面进行一些操作, 这些只是为了让我们看到效果. 但是实际工作中, 是没有人会去关注它的效果的, 而是直接查看自动化执行的结果.
前面的操作都是可以看见浏览器的各种行为的, 叫做有头模式(看得见/前台). 而接下来就是设置无头模式(看不见/后台).
publicvoidnoHeadController(){// 先创建选项对象, 然后再设置浏览器参数 (无头模式)EdgeOptions options =newEdgeOptions();
options.addArguments("-headless");EdgeDriver driver =newEdgeDriver(options);// 访问百度首页, 搜索xxx, 回车
driver.get("https://www.baidu.com");
driver.findElement(By.cssSelector("#kw")).sendKeys("孙宇航");
driver.findElement(By.cssSelector("#su")).click();
driver.quit();}
浏览器的参数设置需要在创建浏览器对象之前进行设置.
版权归原作者 小孙的代码星球 所有, 如有侵权,请联系我们删除。