目录
7.1 窗口的大小设置(manage().window())
谷歌浏览器升级到111版本之后,Java版本的selenium和Chrome不兼容
所以更换浏览器和驱动,使用edge浏览器和edge驱动,因为本篇是在 chrome 浏览器 111 版本之前写的,所以在看到创建 ChromeDriver driver = new ChromeDriver(); 驱动对象的操作,请将这段代码替换为
EdgeOptions options = new EdgeOptions(); options.addArguments("-remote-allow-origins=*"); EdgeDriver driver = new EdgeDriver(options)
- EdgeOptions 是用于设置 Edge 浏览器的选项的类;
- options.addArguments("-remote-allow-origins=*") 是设置 Edge 浏览器允许跨域请求的选项,即允许 WebDriver 与浏览器在不同的域之间通信。
- 如果不使用 EdgeOptions 对象来设置,就无法实现这个功能。而 ChromeDriver 则没有类似的选项需要设置,所以可以直接使用 ChromeDriver driver = new ChromeDriver() 来创建驱动对象但因为版本不兼容就不用 chrome 了。
我本人使用的是chrome的Version 103.0.5060.134 (Official Build) (64-bit)
作用:通过自动化测试有效减少人力的投入,同时提高了测试的质量和效率
概念:自动化测试指软件测试的自动化,在预设状态下运行应用程序或者系统,预设条件包括正常和异常,最后评估运行结果。将人为驱动的测试行为转化为机器执行的过程。
比如,回归测试版本越来越多,版本回归的压力越来越大,仅通过人工测试来回归所有的版本肯定是不现实的,所以我们需要借助自动化测试。
- 接口自动化测试
- UI自动化测试(界面测试)
- 移动端自动化测试
- web 端自动化测试
- 开源免费
- 支持多浏览器(Chrome,FireFox,IE浏览器等)
- 支持多系统(Linux,Windows,MacOS等等)
- 支持多语言(Java,Python,Ruby,JavaScript,Kotlin等等)
- selenium 包提供了很多可供选择的API
如果想要使用 selenium 实施 Web 自动化测试,需要的环境是什么:
Edg浏览器、edg驱动(EdgeDriver)、selenium 工具包
人工测试的情况下,人来手动的打开浏览器,那么驱动就是人力
对自动化来说,代码不能够直接打开浏览器,需要借助驱动程序才能打开浏览器
selenium 编写的自动化脚本是如何打开浏览器(selenium Driver 浏览器三者之间的关系)
驱动要接受 selenium 脚本发送过来的 http 请求并解析
首先先导入 selenium 包
-
-
org.seleniumhq.selenium -
selenium-java -
3.0.0 -
简单自动化示例主要包含五个步骤:
- 创建驱动实例,创建会话(实例化 ChromeDriver 对象)
- 访问网站(对象.get(“网站”))
- 查找元素(对象.findElement(By.cssSelector(“#网址元素id”)).sendKeys(“输入内容”))
- 操作元素(对象.findElement(By.cssSelector(“#网址元素id”)).click())
- 结束会话(对象.quit())
- package com.autotest0113;
-
- import org.openqa.selenium.By;
- import org.openqa.selenium.WebElement;
- import org.openqa.selenium.chrome.ChromeDriver;
-
- import java.util.List;
-
- public class FirstAutotest {
- // 在百度网址搜索关键词 “胡歌”
- public void yifei() throws InterruptedException {
- // 1.打开浏览器
- ChromeDriver chromeDriver = new ChromeDriver();
- Thread.sleep(3000);
- // 2.在浏览器里输入百度网址,访问百度首页
- chromeDriver.get("https://www.baidu.com");
- Thread.sleep(3000);
- // 3.找到百度首页输入框元素,并输入关键词 “胡歌”
- chromeDriver.findElement(By.cssSelector("#kw")).sendKeys("刘亦菲");
- Thread.sleep(3000);
- // 4.找到百度首页 “百度一下” 按钮,并点击一下
- chromeDriver.findElement(By.cssSelector("#su")).click();
- Thread.sleep(3000);
- // 5.结束会话(关闭浏览器)
- chromeDriver.quit();
- }
- }
- package com.autotest0113;
-
- import sun.text.normalizer.CharTrie;
-
- public class RunAutoTest {
- public static void main(String[] args) throws InterruptedException {
- FirstAutotest firstAutotest = new FirstAutotest();
- firstAutotest.huge();
- }
- }
参数:By类(提供通过什么方式来查找元素)
返回值:webElement
当元素可以在页面中被正常查找,程序正常退出
当元素不能在页面中被正常查找,程序执行报错
参数:By 类(提供通过什么方式来查找元素)
返回值:List
- public void methodTest() {
- ChromeDriver driver = new ChromeDriver();
- driver.get("https://www.baidu.com");
- driver.findElement(By.cssSelector("#kw"));
- List
elements= driver.findElements(By.className("hotsearch-item")); - for (WebElement element : elements) {
- System.out.println(element.getText());
- }
-
- driver.findElement(By.cssSelector("#su"));
- driver.quit();
- }
语法:
- 层级:/子级 // 跳级
- 属性:@
- 函数:contains()....
自动化里要求元素的定位必须要唯一,但是手动在页面复制 selector 或者 path 元素不一定是唯一的,需要我们进行手动修改到唯一
sendKeys,仅适用于文本字段和内容可编辑的元素
-
- driver.get("https://www.baidu.com");
- WebElement element = driver.findElement(By.cssSelector("#kw"));
- element.sendKeys("豆腐乾净搞方规");
- // driver.findElement(By.cssSelector("#kw")).sendKeys("豆腐乾净搞方规");
- driver.quit();
driver.findElement(By.cssSelector("#su")).click();
submit 仅适用于表单元素,selenium 官方不推荐使用 submit,更推荐 click
- driver.findElement(By.cssSelector("#kw")).sendKeys("豆腐乾净搞方规");
- driver.findElement(By.cssSelector("#su")).submit();
- Thread.sleep(2000);
- driver.quit();
clear:适用于频繁测试输入是否可以重复输入
- // 清除输入框的内容
- driver.findElement(By.cssSelector("#kw")).clear();
- // 获取文本
- String text = driver.findElement(By.cssSelector("#s-top-left > div > a")).getText();
- System.out.println("获取到的文本:" + text);
-
- // 获取属性的值
- String buttonText = driver.findElement(By.cssSelector("#su")).getAttribute("type");
- System.out.println("获取到的属性名:" + buttonText);
- String buttonText1 = driver.findElement(By.cssSelector("#su")).getAttribute("id");
- System.out.println("获取到的属性名:" + buttonText1);
- String buttonText2 = driver.findElement(By.cssSelector("#su")).getAttribute("value");
- System.out.println("获取到的属性名:" + buttonText2);
- System.out.println(driver.getTitle());
- System.out.println(driver.getCurrentUrl());
- driver.findElement(By.cssSelector("#kw")).sendKeys("你好");
- driver.findElement(By.cssSelector("#su")).click();
- System.out.println(driver.getTitle());
- System.out.println(driver.getCurrentUrl());
最大化,最小化,全屏窗口,手动设置窗口大小
- public void windowConTrol() throws InterruptedException {
- 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(new Dimension(1024,768));
- Thread.sleep(2000);
-
- driver.quit();
- }
打开百度首页,点击图片超链接进入到百度图片首页,获取百度图片页面的 “百度一下” 按钮,正常步骤是会报错的
- // 窗口切换
- driver.get("https://www.baidu.com");
- driver.findElement(By.cssSelector("#s-top-left > a:nth-child(6)")).click();
- Thread.sleep(3000);
- driver.findElement(By.cssSelector("#homeSearchForm > span.s_btn_wr > input"));
- driver.quit();
这是因为虽然我们超过到了百度图片页面,但是当浏览器每次打开一个标签页的时候,会自动的给每个标签页进行标识,这个叫做句柄
可以通过 getWindowHandles() 获取所有标签页的句柄 Set,然后再通过getWindowHandle() 获取当前页面的句柄,然后遍历所有标签页的句柄,如果当前页的句柄和遍历 Set 中的句柄不同,就通过 switchTo().window() 方法进行窗口切换
- public void windowConTrol() throws InterruptedException, IOException {
- driver.get("https://www.baidu.com");
- driver.findElement(By.cssSelector("#s-top-left > a:nth-child(6)")).click();
- Thread.sleep(3000);
- // 获取当前页面的句柄
- String curHandle = driver.getWindowHandle();
- System.out.println("当前页面的句柄:" + curHandle);
- // 获取所有标签的句柄
- Set
handles = driver.getWindowHandles(); - for (String handle : handles) {
- if(handle != curHandle) {
- driver.switchTo().window(handle);
- }
- }
- driver.findElement(By.cssSelector("#homeSearchForm > span.s_btn_wr > input"));
- Thread.sleep(3000);
- driver.quit();
- }
但是当我们打开了好几个窗口,应该怎么切换?
自动化基本没有这样的场景,因为当页面多了不会使用这样的页面跳转了,而是直接去访问要测试的页面,所以这里不用考虑太多
添加 Maven
-
-
-
commons-io -
commons-io -
2.6 -
需要注意的一点是,当代码执行到查找结果页面元素的时候,页面还没有加载完全,此时程序执行的速度是比,页面渲染的速度更快的,所以要注意在代码中添加等待机制,让页面先渲染一下,再截图。
- driver.get("https://www.baidu.com");
- driver.findElement(By.cssSelector("#kw")).sendKeys("刘亦菲");
- driver.findElement(By.cssSelector("#su")).click();
- Thread.sleep(3000);
- // 屏幕截图(保存现场)
- File srcfile = driver.getScreenshotAs(OutputType.FILE);
- // 把屏幕截图好的文件放到指定当前项目的路径下
- String filename = "cur.png";
- FileUtils.copyFile(srcfile,new File(filename));
- driver.findElement(By.cssSelector("#\\31 > div > div > div > div > div > div.cos-row.row-text_Johh7.row_5y9Az > div > div.title-wrapper_XLSiK > a > div > p > span > span"));
- driver.quit();
- 强制等待
- 隐式等待
- 显示等待
- 流畅等待
需要注意:显示等待、隐式等待,不能同时使用,同时使用可能会出现意想不到的等待结果
程序阻塞进行:Thread.sleep()
这个就会使 程序阻塞进行,这种方式在自动化测试中会用到,但用的不是特别多,这是因为
每一个自动化方法就是一个自动化测试用例,比如一个用例需要 10s,100测试用例 1000s,200个用例 2000s,这样耗费时间太多了,只能接受十几秒或几分钟内
隐式等待会作用与 driver 的整个生命周期,隐式等待会一直轮询判断元素算法存在,如果不存在就等待设置好的时间不断的进行轮询,直到元素被找到,在这里设置的是 3s ,在这三秒钟会一直询问是否完成当前行的代码的要求,也就是说每行代码在超过三秒未被执行完全就报错
- public class autoTest {
-
- public void waitContro() {
- ChromeOptions options = new ChromeOptions();
- // 添加隐式等待
- 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("#content_left"));
- driver.quit();
- }
- }
显示等待会等到设置的命令再进行等待
- public class autoTest {
-
-
- public void webDriverWait(){
- ChromeOptions options = new ChromeOptions();
- driver.get("https://www.baidu.com");
- driver.findElement(By.cssSelector("#kw")).sendKeys("刘亦菲");
- driver.findElement(By.cssSelector("#su")).click();
- // 添加显示等待
- new WebDriverWait(driver,Duration.ofSeconds(5)).until(driver->driver.findElement(By.cssSelector("#content_left")));
- driver.quit();
- }
- }
浏览器的前进(forward)、后退(back)、刷新(refresh)
- public void navigateControl() throws InterruptedException {
- ChromeOptions options = new ChromeOptions();
- // 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();
- }
弹窗的类型:
- 警告弹窗
- 确认弹窗
- 提示弹窗
处理弹窗的步骤:
- 将 driver 作用到弹窗上(切换到弹窗)driver.switchTo.alert()
- 选择确认 accept() / 取消 dismiss()(提示弹窗输入文本 sendkeys )
- 虽然警告弹窗只有确认按钮,但 accept 和 dismiss 都能处理
- 虽然警告弹窗和确认弹窗都没有输入文本的地方,但如果要执行 alert.sendKeys 代码,也是不会报错的
- public void AlertControl() throws InterruptedException {
- driver.get("file:///D:/%E6%8F%90%E7%A4%BA%E5%BC%B9%E7%AA%97.html");
- Thread.sleep(3000);
- driver.findElement(By.cssSelector("body > input[type=button]")).click();//找到选择框元素
- Thread.sleep(3000);
- // 切换到弹窗进行弹窗处理
- Alert alert = driver.switchTo().alert();//创建选择框对象
- Thread.sleep(3000);
- // 1. 输入
- alert.sendKeys("666");
- Thread.sleep(3000);
- // 2. 点击确认
- alert.accept();
- Thread.sleep(3000);
- // 取消
- alert.dismiss();
- driver .quit();
- }
选择框的选择方式:
- 根据文本来选择
- 根据属性值来选择
- 根据序号来选择
- public void selectControl() throws InterruptedException {
- driver.get("file:///D:/%E9%80%89%E6%8B%A9%E6%A1%86.html");
- WebElement element = driver.findElement(By.cssSelector("Mathnumber"));
- Thread.sleep(3000);
- // 1.创建选择框对象
- Select select = new Select(element);
- Thread.sleep(3000);
- //1)根据文本来选择
- // select.selectByVisibleText("123");
- // //2)根据属性值来选择
- // select.selectByValue("234");
- // //3)根据序号来选择
- // select.selectByIndex(2);
- Thread.sleep(3000);
- driver.quit();
- }
executeScript(参数:JS)
- void scriptControl() throws InterruptedException {
- driver.get("https://image.baidu.com/");
- Thread.sleep(3000);
- // 执行js命令,让页面置底
- // driver.executeScript("document.documentElement.scrollTop=500");
- // Thread.sleep(3000);
- // // 执行js命令,让页面置顶,0 就是顶部
- // driver.executeScript("document.documentElement.scrollTop=0");
- // Thread.sleep(3000);
- driver.executeScript("var ss = document.querySelector(\"#kw\");ss.value = '刘亦菲';");//通过js代码来实现搜索
- Thread.sleep(3000);
- driver.quit();
- }
sendKeys("文件路径+文件")
- void fileUploadControll() throws InterruptedException {
- driver.get("file:///D:/%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0.html");
- driver.findElement(By.cssSelector("#avatar")).sendKeys("D:\\Desktop\\CSDN封面图片\\u=1008366999,1348072899&fm=253&fmt=auto&app=120&f=JPEG.webp");
- Thread.sleep(3000);
- driver.quit();
- }
无头模式:在实际工作中,测试人员将自动化部署在机器上自动的执行,测试人员看不到测试过程,而是直接查看自动化执行的结果
有头模式:就是程序在自动的测试,我们是可以看到执行测试的过程界面
浏览器的参数设置需要在创建浏览器对象之前
- void paramsControl(){
- // 百度搜索刘亦菲
- // 先创建选项对象,然后再设置浏览器参数
- ChromeOptions options = new ChromeOptions();
- options.addArguments("-headless");
- // options.addArguments("--remote-allow-origins=*");
- ChromeDriver driver = new ChromeDriver(options);
- driver.get("https://image.baidu.com/");
- driver.executeScript("var ss = document.querySelector(\"#kw\");ss.value = '刘亦菲';");
- }