Selenium之路: UI自动化测试的必备指南

文章目录

  • 一. 什么是自动化测试
  • 二. selenium的介绍
    • 1. Selenium是什么
    • 2. Selenium的工作原理
    • 3. Selenium 的环境搭建
  • 三. webdriver API
    • 1. 元素的定位
      • 1.1 CSS 定位
      • 1.2 XPath 定位
      • 1.3 实现一个自动化需求
    • 2. 操作测试对象
      • 2.1 clear 清除对象输入的文本内容
      • 2.2 submit 提交
      • 2.3 getAttribute 获取元素对应属性的值
    • 3. 添加等待
      • 3.1 隐式等待
      • 3.2 显式等待
    • 4. 打印信息
    • 5. 浏览器的操作
    • 6. 键盘事件
    • 7. 鼠标事件
    • 7. 定位一组元素
    • 8. 多层框架/窗口定位
    • 9. 下拉框处理
    • 10. alert弹窗的处理
    • 11. 上传文件操作
    • 12. 关闭浏览器
    • 13. 切换窗口
    • 14. 截图

一. 什么是自动化测试

自动化测试指软件测试的自动化,可以使用软件工具或脚本来执行测试任务的过程,以替代人工进行重复性、繁琐或耗时的测试活动;是将人为驱动的测试行为转化为机器执行的过程 。

自动化测试包括 UI 自动化,接口自动化,单元测试自动化。

二. selenium的介绍

1. Selenium是什么

Selenium 是 Web 应用中基于 UI 的自动化测试框架,它的优点如下:

  1. 开源免费。
  2. 支持多浏览器,比如 Chrome,Edge,Firefox,Safari 等。
  3. 支持多语言,包括 Java,Python,C# 等,都可以使用 Selenium 这个工具。
  4. 支持多操作系统,比如 Windows,Linux,Mac 等。
  5. Selenium 的底层封装了丰富的 API,可以直接拿来使用。

2. Selenium的工作原理

img

🍂用 Selenium 实现自动化,主要需要三个东西:

  1. 自动化测试代码:自动化测试代码发送请求给浏览器的驱动。
  2. 浏览器驱动:它来解析这些自动化测试的代码,解析后把它们发送给浏览器。
  3. 浏览器:执行浏览器驱动发来的指令,并最终完成工程师想要的操作。

🍂Selenium 脚本执行时后端实现的流程:

  1. 对于编写的每一条 Selenium 脚本测试代码,都会创建一个 Http 请求并且发送给浏览器的驱动。
  2. 浏览器驱动中包含了一个 HTTP Server,用来接收这些 Http 请求。
  3. HTTP Server 接收到请求后,浏览器驱动程序会将请求解析成浏览器可以识别的命令并发送给浏览器。
  4. 浏览器执行接收到的命令,例如导航至指定 URL、查找和操作页面上的元素等。
  5. 浏览器将执行结果返回给 HTTP Server。
  6. HTTP Server 又将结果返回给 Selenium 的脚本,以便进行进一步的处理和验证。

3. Selenium 的环境搭建

我这里演示的是使用 Java + Selenium 来进行自动化测试的教程,使用的 JDK 的是 1.8 版本,JDK 1.8 可以兼容 Selenium 2.x、3.x 和 4.x 版本,浏览器使用的是 Chrome。

1️⃣第一步,查看自己 Chrome 浏览器的版本。

imgimg

2️⃣第二步,点击下面链接下载相应版本浏览器驱动。

ChromeDriver - WebDriver for Chrome - Downloads (chromium.org)

img

找版本前三位数一样的,最后一位如果找不到一样的就找一个最接近的。

img

3️⃣第三步,解压下载好的驱动压缩包,将下载好的 chromedriver.exe 放到 java 系统环境变量下(我这里是C:\Program Files\Java\jdk1.8.0_192\bin) 。

img

4️⃣第四步,打开 IDEA,创建一个 Maven 项目:在 pom.xml 文件中添加以下依赖,添加后记得 reload。

<dependencies>
    <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>3.141.59</version>
    </dependency>
</dependencies>

5️⃣第五步,验证环境是否搭建成功,创建一个类验证下面的代码是否可以运行。

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

public class Main {
    public static void main(String[] args) {
        ChromeOptions options = new ChromeOptions();
        // 允许所有请求
        options.addArguments("--remote-allow-origins=*");
        //创建一个驱动对象来打开浏览器
        WebDriver webDriver = new ChromeDriver();
        // 打开百度首页
        webDriver.get("https://www.baidu.com");
    }
}

如果出现以下内容,则说明 Selenium 环境搭建已经成功。

img

上述代码的含义如下:

ChromeOptions options = new ChromeOptions();
// 允许所有请求
options.addArguments("--remote-allow-origins=*");
// 创建一个驱动对象来打开浏览器
WebDriver webDriver = new ChromeDriver();

前两行代码是为了解决跨域问题,第三行代码是在创建 Chrome 驱动对象,要知道所有的 Selenium 操作都是通过驱动来完成的,所以我们首先需要获取谷歌驱动对象,这三行代码是固定写法。

// 打开百度首页
webDriver.get("https://www.baidu.com");

get() 方法就是获取到对应页面的地址打开页面,也就是获取一个 URL,比如这里就是获取百度首页的地址并打开页面。

此时环境搭建就已经完毕了,接下来介绍 Selenium 的常见 API。

三. webdriver API

1. 元素的定位

假如要测试一个百度网页,输入一个 “Test” ,是否返回 Test 相关数据;此时我们需要找到百度的输入框在哪里,然后输入相关信息,再去找百度一下这个按钮在哪里,然后去点击它,那么代码的测试也是一样的,首先要做的就是定位元素,再进行一些操作。

定位一个元素最常用的是CSS定位和XPath定位,通过这两种定位方式几乎可以找到页面几乎所有的元素,但 CSS 选择器定位元素的方式更高效。

1.1 CSS 定位

在 Web 页面中可以通过以下方式找到 CSS 定位,以百度页面为例,首先打开百度首页,鼠标右键,点检查,打开开发者工具,然后点击箭头,选中输入框,找到对应代码,然后鼠标右键,找到copy,点击Copy selector即可。

img

有了定位就可以配合元素定位方法cssSelector()和寻找元素的方法findElement()使用,sendKeys()里面的内容就是输入框我们想输入的内容;

driver.findElement(By.cssSelector("#kw")).sendKeys("软件测试");

♨️测试案例:实现一个自动化操作,在百度框输入“软件测试”,点击“百度一下”按钮进行搜索。

此时在上面的基础上我们还需要定位到“百度一下”这个按钮,同时使用click()方法来进行点击操作,代码如下:

private static void test() {
    // 创建一个选项
    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();
}
public static void main(String[] args) throws InterruptedException {
    test();
}

执行结果:

img

🎯下面列出几种常见的 CSS 选择器:

  1. 标签选择器:通过标签名称来选择对应的元素。语法形式为 “标签名称”,例如 “div” 表示选择所有的 div 元素。
  2. 类选择器:通过元素的 class 属性值来选择对应的元素。语法形式为 “.class值” ,例如 “.myClass” 表示选择 class 属性值为 “myClass” 的所有元素。
  3. id 选择器:通过元素的 id 属性值来选择对应的元素。语法形式为 “#id值”,例如 “#myElement” 表示选择 id 属性值为 “myElement” 的元素
  4. 属性选择器:通过元素的属性和属性值来选择对应的元素。语法形式为 “[属性=‘属性值’]”,例如 “[href=‘https://example.com’]” 表示选择 href 属性值为 “https://example.com” 的所有元素。
  5. 伪类选择器:通过元素的特定状态或位置来选择对应的元素。常见的伪类选择器包括 :hover(鼠标悬停)、:first-child(第一个子元素)、:last-child(最后一个子元素)等。

1.2 XPath 定位

类似的也可以找到 XPath 定位,鼠标右键,点检查,打开开发者工具,然后点击箭头,选中输入框,找到对应代码,然后鼠标右键,找到copy,点击Copy XPath(相对路径)/Copy full Xpath(绝对路径)即可。

同样配合元素定位方法By.xpath()和寻找元素的方法findElement()使用即可。

WebElement element = webDriver.findElement(By.xpath("//*[@id=\"kw\"]"));

这个就不做冗余的演示了.

🎯这里主要介绍几种常用的 XPath 选择语法:

1️⃣绝对路径:/html/head/title (不常用)

2️⃣相对路径

  1. 相对路径+索引(找下标)//form/span[1]/input,表示在 form 标签下/选中第二个 span 标签/找到 input 标签。
  2. 相对路径+属性值(找相关属性)://input[@class="s_ipt"],表示选取 input 元素中 class 属性值为 s_ipt 的标签。
  3. 相对路径+通配符://*[@*="s_ipt"],表示找到任意属性值为的 s_ipt 的任意标签。
  4. 相对路径+文本匹配//a[text()="新闻"],表示选择文本内容为"新闻"的所有标签。

更多详细的语法可以参考在线教程:w3school 在线教程

1.3 实现一个自动化需求

♨️自动化需求:实现一个在百度的输入框中输入”软件测试“,是否返回对应的数据。

private static void test01() 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.xpath("//*[@id=\"kw\"]"));
    // 输入软件测试
    element.sendKeys("软件测试");
    // 找到搜索按钮, 并进行点击
    webDriver.findElement(By.cssSelector("#su")).click();// 这里也可以使用 submit
    webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.HOURS);
    // 校验搜索出来的结果是不是和软件测试相关的内容
    List<WebElement> elements = webDriver.findElements(By.cssSelector("a em"));
    int flag = 0;
    for (WebElement e : elements) {
        if (e.getText().contains("软件测试")) {
            flag = 1;
            System.out.println("测试通过!");
            break;
        }
    }
    if (flag == 0) {
        System.out.println("测试不通过!");
    }
}
public static void main(String[] args) throws InterruptedException {
    test01();
}

测试结果:

img

2. 操作测试对象

上面主要介绍了元素的定位,但是定位只是第一步,定位之后需要对元素素进行操作,是鼠标点击还是键盘输入,或者清除元素的内容,或者提交表单等。

webdriver 中比较常用的操作对象的方法有下面几个:

操作说明
click点击对象
send_keys在对象上模拟按键输入
clear清除对象输入的文本内容
submit提交
text用于获取元素的文本信息
getAttribute获取元素对应属性的值

2.1 clear 清除对象输入的文本内容

♨️自动化需求:打开一个百度的首页,并且在输入框中输入“测试开发”,并且点击“百度一下”按钮,最后清除输入框内容。

private static void test02() throws 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();
    // 等待3秒
    sleep(3000);
    // 清空百度搜索输入框中的数据
    webDriver.findElement(By.cssSelector("#kw")).clear();
}
public static void main(String[] args) throws InterruptedException {
    test02();
}

测试结果:

img

2.2 submit 提交

这个需要注意的是,如果点击的元素是放在 form 标签中的,此时使用 submit 实现的效果和 click 是一样的;如果点击的元素是放在非 form 标签中,此时使用 submit 会报错。

♨️测试案例:点击百度中的“新闻”超链接,这个超链接没有放在 form 标签中,则会报错。

private static void test03() {
    ChromeOptions options = new ChromeOptions();
    options.addArguments("--remote-allow-origins=*");
    WebDriver webDriver = new ChromeDriver(options);
    webDriver.get("https://www.baidu.com/");
    // 注意这里不能使用 submit, submit 的使用要求标签元素必须在 from 表单内
    webDriver.findElement(By.xpath("//a[text()=\"新闻\"]")).submit();
}
public static void main(String[] args) throws InterruptedException {
    test03();
}

报错了:

img

2.3 getAttribute 获取元素对应属性的值

♨️自动化需求:找到“百度一下”按钮,验证这个按钮 value 属性值是不是“百度一下”,这个值不是放在标签中间,不可以通过 test 来获取,这个时候需要通过 getAttribute 获取元素对应属性的值。

img

private static void test04() {
    ChromeOptions options = new ChromeOptions();
    options.addArguments("--remote-allow-origins=*");
    WebDriver webDriver = new ChromeDriver(options);
    webDriver.get("https://www.baidu.com/");
    // getAttribute获取标签内的属性值, 获取搜索按钮中的 value 属性的值
    String button_value = webDriver.findElement(By.cssSelector("#su")).getAttribute("value");
    if(button_value.equals("百度一下")) {
        System.out.println("测试通过!");
    } else {
        System.out.println(button_value);
        System.out.println("测试不通过!");
    }
}
public static void main(String[] args) throws InterruptedException {
    test04();
}

测试结果:

img

3. 添加等待

等待方式可以分为两大类:

  1. 强制等待:sleep(),这个平时也很常用,就不做过多的介绍了。
  2. 智能等待:隐式等待,显示等待。

🎯隐式等待和显示等待的区别如下:

  1. 作用范围:隐式等待是全局性的等待设置,适用于整个页面的元素定位操作;显示等待是针对特定元素或条件的等待设置,更具体、可定制性更强。
  2. 等待时间:隐式等待只需设置一次,并适用于所有元素的定位操作;显示等待可以根据不同情况设定不同的等待时间。
  3. 等待条件:隐式等待没有明确的等待条件,只要在规定时间内找到元素即可;显示等待可以指定等待元素可见、可点击等特定条件。
  4. 操作方式:隐式等待是自动等待的,不需要在代码中显式调用;显示等待需要在代码中显式调用等待方法。

3.1 隐式等待

隐式等待可以通过添加implicitlyWait()方法就可以方便的实现智能等待,implicitlyWait() 的用法比 sleep() 更智能,后者只能选择一个固定的时间的等待,前者可以在一个时间范围内智能的等待。

webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.DAYS);

隐式地等待并非一个固定的等待时间,当脚本执行所需要的元素都被定位到时,时间没到也会则继续执行后续的代码;如果还有元素定位不到,则它以轮询的方式不断的判断元素是否被定位到,直到超出设置的时长。

♨️测试案例:这里假设等待 3 天时间,设置隐式等待最长等待为 3 天,如果 3 天内获取到页面上的元素,此时执行下边的代码;如果等待 3 天时间还是没有找到这个元素,此会报错。

private static void test02() throws 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();
    // 等待3秒后再清空
    // sleep(3000);
    // 隐式等待, 收集到后面代码所需要的所有元素就会停止等待
    webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.DAYS);
    // 清空百度搜索输入框中的数据
    webDriver.findElement(By.cssSelector("#kw")).clear();
}
public static void main(String[] args) throws InterruptedException {
    test02();
}

执行结果:

img

3.2 显式等待

显式等待与隐式不同,它是等待的是一定的条件,比如等待某个元素可以被被点击,等待元素可见。

♨️这里设置等待条件为,等待页面标题是否为"百度一下,你就知道"。

private static void test05() {
    // 创建驱动
    WebDriver webDriver = new ChromeDriver();
    // 打开百度首页
    webDriver.get("https://www.baidu.com/");
    // 判断元素是否可以被点击
    WebDriverWait wait = new WebDriverWait(webDriver, 1);
    wait.until(ExpectedConditions.titleIs("百度一下,你就知道"));
}
public static void main(String[] args) throws InterruptedException {
    test05();
}

执行结果:

img

4. 打印信息

♨️比如要检验百度首页的 url 和 title 是否符合预期,这里主要会用到了两个函数 getCurrentUrl() 和 getTitle(),它们的返回值类型是 String,所以可以定义两个 String 变量来接收。

private static void test06() {
    ChromeOptions options = new ChromeOptions();
    options.addArguments("--remote-allow-origins=*");
    WebDriver webDriver = new ChromeDriver(options);
    webDriver.get("https://www.baidu.com/");
    String url = webDriver.getCurrentUrl();
    String title = webDriver.getTitle();
    if(url.equals("https://www.baidu.com/") && title.equals("百度一下,你就知道")) {
        System.out.println("当前页面url: " + url + ", 当前页面title: " + title);
        System.out.println("测试通过!");
    } else {
        System.out.println("测试不通过!");
    }
}
public static void main(String[] args) throws InterruptedException {
    test06();
}

测试结果:

img

5. 浏览器的操作

浏览器的操作包括设置浏览器的页面大小,浏览器前进,后退,刷新,滚动条滑动等。

操作说明
webDriver.manage().window().maximize();浏览器的最大化
webDriver.manage().window().setSize(new Dimension(width, high));设置浏览器宽、高
webDriver.navigate().forward();浏览器的前进
webDriver.navigate().back();浏览器的后退
webDriver.navigate().refresh();浏览器的刷新
document.documentElement.scrollTop=0将浏览器滚动条滑到最顶端
document.documentElement.scrollTop=10000将浏览器滚动条滑到最底端

♨️测试案例:先打开一个浏览器,继续打开百度网页,然后让浏览器最大化,接着再让浏览器变为固定的宽和高,让后搜索“白鹿”并且百度一下,进行浏览器回退、浏览器刷新、浏览器前进,再将滚动条滑动最底端,再到最顶部。

浏览器滚动条的控制需要依靠 js 脚本。

private static void test07() throws InterruptedException {
    ChromeOptions options = new ChromeOptions();
    options.addArguments("--remote-allow-origins=*");
    ChromeDriver driver = new ChromeDriver(options);
    driver.get("https://www.baidu.com/");

    // 最大化
    driver.manage().window().maximize();
	sleep(1000);
    // 设置固定宽,高
    driver.manage().window().setSize(new Dimension(1000,800));

    driver.findElement(By.cssSelector("#kw")).sendKeys("白鹿");
    driver.findElement(By.cssSelector("#su")).click();
    sleep(2000);
    // 浏览器回退
    driver.navigate().back();
    sleep(2000);
    // 浏览器刷新
    driver.navigate().refresh();
    sleep(2000);
    // 浏览器前进
    driver.navigate().forward();
    sleep(2000);
    // 将浏览器滚动条滑到最底端  JS脚本强制转换
    ((JavascriptExecutor)driver).executeScript("document.documentElement.scrollTop=10000");
    sleep(2000);
   // 将浏览器滚动条滑到最顶端
    ((JavascriptExecutor)driver).executeScript("document.documentElement.scrollTop=0");
}
public static void main(String[] args) throws InterruptedException {
    test07();
}

测试结果:

img

6. 键盘事件

这个操作是让自动化代码在运行过程中可以进行点击键盘上的按键操作,可以通过 send_keys() 方法和 Keys 类的常量来模拟键盘操作。

操作说明
send_keys(Keys.TAB)# TAB
send_keys(Keys.ENTER)# 回车
send_keys(Keys.SPACE)#空格键
send_keys(Keys.ESCAPE)#回退键(Esc)
send_keys(Keys.CONTROL,‘a’)#全选(Ctrl+A)
send_keys(Keys.CONTROL,‘c’)#复制(Ctrl+C)
send_keys(Keys.CONTROL,‘x’)#剪贴(Ctrl+X)
send_keys(Keys.CONTROL,‘v’)#粘贴(Ctrl+V)

例如:

private static void test08() throws InterruptedException {
    WebDriver webDriver = new ChromeDriver();
    webDriver.get("https://www.baidu.com/");
    webDriver.findElement(By.cssSelector("#kw")).sendKeys("白鹿");
    sleep(3000);
    //ctrl+A
    webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL, "A");
    sleep(3000);
    //ctrl+X
    webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL, "X");
    //ctrl+V
    sleep(3000);
    webDriver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL, "V");
}
public static void main(String[] args) throws InterruptedException {
    test08();
}

执行结果:

img

7. 鼠标事件

要使用鼠标事件需要导入工具包:

import org.openqa.selenium.interactions.Actions;

语法:

#鼠标拖动事件
Actions(webDriver).moveToElement(webElement).contextClick().perform();

Actions(webDriver):生成用户的行为。

moveToElement(element):移动鼠标到一个元素上。

perform():执行所有存储的行为。

常用鼠标事件如下:

操作说明
contextClick()右击
doubleClick()双击
dragAndDrop()拖动
dragAndDrop()移动

♨️测试案例:打开百度首页,搜索“520”并且百度一下,把鼠标放在图片的按钮上进行右击。

private static void test09() throws InterruptedException {
    WebDriver webDriver = new ChromeDriver();
    webDriver.get("https://www.baidu.com/");
    webDriver.findElement(By.cssSelector("#kw")).sendKeys("520");
    webDriver.findElement(By.cssSelector("#su")).click();
    sleep(3000);
    // 找到图片按钮
    WebElement webElement = webDriver.findElement(By.cssSelector("#s_tab > div > a.s-tab-item.s-tab-item_1CwH-.s-tab-pic_p4Uej.s-tab-pic"));
    // 鼠标右击出现框
    Actions actions = new Actions(webDriver);
    sleep(2000);
    //contextClick()右击鼠标
    actions.moveToElement(webElement).contextClick().perform();
}
public static void main(String[] args) throws InterruptedException {
    test09();
}

执行结果:

img

7. 定位一组元素

webdriver 可以很方便的使用findElement方法来定位某个特定的对象,不过有时候我们却需要定位一组对象,这时候就需要使用findElements方法。
定位一组对象一般用于以下场景:

  • 批量操作对象,比如将页面上所有的checkbox都勾上。
  • 先获取一组对象,再在这组对象中过滤出需要具体定位的一些对象。比如定位出页面上所有的checkbox,然后选择最后一个。

有以下页面:

用浏览器打开这个如下页面我们看到三个复选框和两个单选框。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <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>

img

♨️下面我们就来定位这三个复选框,然后将这三个checkbox都勾上。

private static void page01() {
    WebDriver webDriver = new ChromeDriver();
    webDriver.get("http://localhost:63342/_20230925testcode/src/main/Page/test01.html?_ijt=hk3glm0bcb2222roak6kf4826i&_ij_reload=RELOAD_ON_SAVE");
    webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.DAYS);
    List<WebElement> webElements = webDriver.findElements(By.cssSelector("input"));
    for(int i = 0; i < webElements.size(); i++) {
        // 如果每个元素type值等于checkbox进行点击
        // getAttribute获取页面上的元素属性值,里面的type是当前元素属性
        if(webElements.get(i).getAttribute("type").equals("checkbox")){
            webElements.get(i).click();
        } else {
            // 否则什么也不操作
            ;
        }
    }
}
public static void main(String[] args) throws InterruptedException {
    page01();
}

这个代码使用 List 来存储所有是 input 标签的元素,其中每个可以勾选的按钮都带有 type 属性,那么就可以使用方法 getAttribute(“type”) 来定位到一些指定元素,定位到之后进行 click() 点击操作即可。

执行结果:

img

8. 多层框架/窗口定位

对于一个web应用,经常会出现框架(yrame或)窗口(window)的应用,这也就给我们的定位带来了一定的困难。

  • 定位一个frame : switchTo.frame(name or id or frameElement),通过 frame 的 id 或者 name 或者 frame 自带的其它属性来定位框架,这里switchTo.frame()把当前定位的主体切换了frame里。
  • switchTo.defaultContent:从 frame 中嵌入的页面里跳出,跳回到最外面的默认页面中。
  • 定位一个窗口window: switchTo.window(name_or_id_or_frame_element)

有以下页面:

frame.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <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:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <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>

img

♨️这里我们要定位到页面中 click 这个弹窗元素。

要注意不可以直接用 webDriver.findElement(By.cssSelector(" ")).click();,此时这个页面中 frame 里边的元素是获取不到的。

正确的做法是先通过 switchTo.frame() 方法将定位到指定框架,再通过一般方式定位框架中的元素。

private static void page02() {
    WebDriver webDriver = new ChromeDriver();
    webDriver.get("http://localhost:63342/T-20230515/src/main/Page/test02.html");
    webDriver.switchTo().frame("f1");
    webDriver.findElement(By.cssSelector("body > div > div > a")).click();
}
public static void main(String[] args) throws InterruptedException {
    page02();
}

执行结果:

img

9. 下拉框处理

下拉框是我们最常见的一种页面元素,对于一般的元素,我们只需要一次就定位,但下拉框里的内容需要进行两次定位,先定位到下拉框select,再定位到下拉框内里的选项option

这里主要会用到一个 Select 方法,使用先要创建一个 Select 对象,然后去调用里面对应的方法,常见的使用下标定位(Index,从0开始)或者通过 Value 来进行定位。

有以下界面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>select</title>
</head>
<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>

img

♨️我们分别用下标定位第 4 个元素,用 值 Value 值 定位第一个元素。

代码实现:

private static void page03() {
    WebDriver webDriver = new ChromeDriver();
    webDriver.get("http://localhost:63342/T-20230515/src/main/Page/test03.html");
    WebElement webElement = webDriver.findElement(By.cssSelector("#ShippingMethod"));
    Select select = new Select(webElement);
    // 通过下标来选择
    // select.selectByIndex(3);
    // 通过value值来选择
    select.selectByValue("12.51");
}
public static void main(String[] args) throws InterruptedException {
	page03();
}

执行结果:

img

img

10. alert弹窗的处理

通过 switchTo.alert() 处理原生的 alert 弹窗。

操作说明
webDriver.switchTo().alert().text()返回 alert 中的文字信息
webDriver.switchTo().alert().accept()点击确认按钮
webDriver.switchTo().alert().dismiss()点击取消按钮
webDriver.switchTo().alert()dismiss()输入值,如果 alert 没有对话框就不能用了,不然会报错

有以下页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <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>

img

♨️测试案例:代码编写一个 alert 弹窗,在弹窗中输入"韵秋梧桐",随后 alert 弹窗确认。

private static void page04() throws InterruptedException {
    WebDriver webDriver = new ChromeDriver();
    webDriver.get("http://localhost:63342/T-20230515/src/main/Page/test04.html");
    webDriver.findElement(By.cssSelector("button")).click();
    sleep(3000);
    // alert弹窗取消
    webDriver.switchTo().alert().dismiss();
    sleep(3000);
    // 点击按钮
    webDriver.findElement(By.cssSelector("button")).click();
    // 在alert弹窗中输入"韵秋梧桐"
    webDriver.switchTo().alert().sendKeys("韵秋梧桐");
    // alert弹窗确认
    sleep(3000);
    webDriver.switchTo().alert().accept();
}
public static void main(String[] args) throws InterruptedException {
	page04();
}

执行结果:

img

11. 上传文件操作

手动的上传操作一般要打开一个本地窗口,从窗口选择本地文件添加。

而这里只需要要定位上传按钮,通过 sendKeys() 添加本地文件路径就可以了,绝对路径和相对路径都可以,关键是上传的文件存在。

有如下页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>upload_file上传文件</title>
</head>
<body>
    <input type="file">
</body>
</html>

img

img

♨️测试案例:实现一个上传文件需求

private static void page05() {
    WebDriver webDriver = new ChromeDriver();
    webDriver.get("http://localhost:63342/T-20230515/src/main/Page/test05.html");
    webDriver.findElement(By.cssSelector("input")).sendKeys("D:\\img\\cat1.jpg");
}
public static void main(String[] args) throws InterruptedException {
	page05();
}

测试结果:

img

12. 关闭浏览器

关闭操作分为两种:

  1. quit() :关闭整个浏览器,并且清空缓存。
  2. close() :只是关闭原始窗口(源页面),不会清空缓存。

♨️测试案例:打开百度首页,点击新闻按钮,通过 quit 和 click 方法关闭浏览器。

img

private static void test10() throws InterruptedException {
    WebDriver webDriver = new ChromeDriver();
    webDriver.get("https://www.baidu.com/");
    // 找到新闻按钮并点击
    webDriver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();
    sleep(2000);
    webDriver.quit();
    // webDriver.close();
}
public static void main(String[] args) throws InterruptedException {
	test10();
}

使用 quit 执行结果:

img

使用 close 执行结果:

img

13. 切换窗口

我们在设计自动化代码的时候,可能会遇到页面从当前页面跳转到另一个新的页面,那么这个时候再直接去使用 cssSelector 或者 Xpath 方法去定位元素的话,肯定是定位不到的,因为跳转到了新的页面,get 方法打开的是旧的页面,比如当我们从百度页面打开新闻页面的时候,此时我们如果想要在新闻页面操作百度一下,那么就得切换窗口。

此时我们可以使用getWindowHandles()获取全部的窗口句柄(getWindowHandle 是获取 get 打开的页面窗口句柄),遍历存储全部句柄的Set获取到我们需要的最后一个句柄,然后就通过webDriver.switchTo().window()来切换窗口了。

♨️测试案例:打开百度首页,点击新闻按钮,在百度新闻框输入“新闻联播”并且点击百度一下

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();
    sleep(1000);
    // 通过getWindowHandles获取所有的窗口句柄
    // 通过getWindowHandle获取的get打开的页面窗口句柄
    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);
    sleep(3000);
    // 在输入框中搜索新闻联播
    webDriver.findElement(By.cssSelector("#ww")).sendKeys("新闻联播");
    // 点击"百度一下"
    webDriver.findElement(By.cssSelector("#s_btn_wr")).click();
}

执行结果:

img

14. 截图

这个操作的话就是会在指定的页面进行截图,然后保存到对应的路径,在实际工作中对比与我们的预期结果是否一致。

首先需要在我们的配置文件pom.xml中导入依赖;

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

截图操作:((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);

复制到硬盘:FileUtils.copyFile(File srcFile, File destFile);

♨️测试案例:打开百度首页,输入“软件测试”,对测试页面进行截图

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();
    sleep(3000);
    // 强转成截图对象
    File file = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);
    // 将截图好的图片存储到D:\img\jietu01.png路径下
    FileUtils.copyFile(file, new File("D:\\img\\jietu01.png"));
}
public static void main(String[] args) throws InterruptedException, IOException {
    test12();
}

测试结果:

截图已经保存到了指定路径

img


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/121711.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

四川思维跳动商务信息咨询有限公司可信吗?

在今天的数字化时代&#xff0c;抖音带货已成为一种全新的商业模式。许多公司都在通过这种形式进行产品推广和销售&#xff0c;其中&#xff0c;四川思维跳动商务信息咨询有限公司以其专业的服务和良好的信誉&#xff0c;在抖音带货领域赢得了广泛赞誉。 四川思维跳动商务信息…

Docker:容器网络互联

Docker&#xff1a;容器网络互联 1. 网络2. 自定义网络 1. 网络 默认情况下&#xff0c;所有容器都是以bridge方式连接到Docker的一个虚拟网桥上&#xff1a; [root172 demo]# docker inspect mysql [root172 demo]# docker inspect dd 在dd容器中ping mysql 但是存在问题&a…

算法通过村第十八关-回溯|白银笔记|经典问题

文章目录 前言组合总和问题分割回文串子集问题排序问题字母大小写全排列单词搜索总结 前言 提示&#xff1a;我不愿再给你写信了。因为我终于感到&#xff0c;我们的全部通信知识一个大大的幻影&#xff0c;我们每个人知识再给自己写信。 --安德烈纪德 回溯主要解决一些暴力枚举…

使用Go语言抓取酒店价格数据的技术实现

目录 一、引言 二、准备工作 三、抓取数据 四、数据处理与存储 五、数据分析与可视化 六、结论与展望 一、引言 随着互联网的快速发展&#xff0c;酒店预订已经成为人们出行的重要环节。在选择酒店时&#xff0c;价格是消费者考虑的重要因素之一。因此&#xff0c;抓取酒…

Pytorch tensor 数据类型快速转换三种方法

目录 1 通用,简单&#xff0c;CPU/GPU tensor 数据类型转换 2 tensor.type()方法 CPU tensor 数据类型转换 GPU tensor 数据类型转换 3 tensor.to() 方法,CPU/GPU tensor 数据类型转换 1 通用,简单&#xff0c; CPU/GPU tensor 数据类型转换 tensor.double()&#xff1a;…

使用Keras建立模型并训练等一系列操作方式

由于Keras是一种建立在已有深度学习框架上的二次框架&#xff0c;其使用起来非常方便&#xff0c;其后端实现有两种方法&#xff0c;theano和tensorflow。由于自己平时用tensorflow&#xff0c;所以选择后端用tensorflow的Keras&#xff0c;代码写起来更加方便。 1、建立模型 …

玩转Apipost-Helper:代码编辑器内调试、生成文档

Apipost-Helper是由Apipost推出的IDEA插件&#xff0c;写完接口可以进行快速调试&#xff0c;且支持搜索接口、根据method跳转接口&#xff0c;还支持生成标准的API文档&#xff0c;注意&#xff1a;这些操作都可以在代码编辑器内独立完成&#xff0c;非常好用&#xff01;这里…

SSM之spring注解式缓存redis

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《Spring与Mybatis集成整合》《Vue.js使用》 ⛺️ 越努力 &#xff0c;越幸运。 1.Redis与SSM的整合 1.1.添加Redis依赖 在Maven中添加Redis的依赖 <redis.version>2.9.0</redis.…

axios请求的问题

本来不想记录&#xff0c;但是实在没有办法&#xff0c;因为总是会出现post请求&#xff0c;后台接收不到数据的情况,还是记录一下如何的解决的比较好。 但是我使用export const addPsiPurOrder data > request.post(/psi/psiPurOrder/add, data); 下面是封装的代码。后台接…

kubernetes (k8s)的使用

一、kubernetes 简介 谷歌2014年开源的管理工具项目&#xff0c;简化微服务的开发和部署。 提供功能&#xff1a;自愈和自动伸缩、调度和发布、调用链监控、配置管理、Metrics监控、日志监控、弹性和容错、API管理、服务安全等。官网&#xff1a;https://kubernetes.io/zh-cn…

算法记录|笔试中遇到的题

栈 394. 字符串解码730.统计不同回文子序列 394. 字符串解码 我自己写的方法 class Solution {public String decodeString(String s) {char[] chs s.toCharArray();LinkedList<Character> stack new LinkedList<>();for(char ch:chs){if(ch]){stack helper(st…

微信管理系统:让企业更轻松地管理客户和员工资源

在日常工作中&#xff0c;我们经常遇到以下问题&#xff1a; ①由于微信号众多&#xff0c;需要频繁地在不同设备之间切换&#xff0c;这严重影响了工作效率。 ②尽管我一直努力回复客户的消息&#xff0c;但有时还是无法做到即时回复&#xff0c;这给客户带来了一些不便。 …

fpga时序相关概念与理解

一、基本概念理解 对于数字系统而言&#xff0c;建立时间&#xff08;setup time&#xff09;和保持时间&#xff08;hold time&#xff09;是数字电路时序的基础。数字电路系统的稳定性&#xff0c;基本取决于时序是否满足建立时间和保持时间。 建立时间Tsu&#xff1a;触发器…

基于BP神经网络+Adaboost的强分类器设计实现公司财务预警

大家好&#xff0c;我是带我去滑雪&#xff01; Adaboost算法的思想是合并多个弱分类器的输出以产生有效分类。其主要步骤是先利用弱学习算法进行迭代运算&#xff0c;每次运算都按照分类结果更新训练数据权重分布&#xff0c;对于分类失败的训练个体赋予较大的权重&#xff0c…

HCIA-单臂路由-VLAN-VLAN间通信-OSPF 小型实验

HCIA-单臂路由-VLAN-VLAN间通信-OSPF 实验拓扑配置步骤第一步 配置二层VLAN第二步 配置VLANIF和IP地址第三步 配置OSPF 配置验证PC1可以ping通PC2 PC3 PC4 实验拓扑 配置步骤 第一步 配置二层VLAN 第二步 配置VLANIF和IP地址 第三步 配置OSPF 第一步 配置二层VLAN SW1 sysna…

Blender vs 3ds Max:谁才是3D软件的未来

在不断发展的3D建模和动画领域&#xff0c;两大软件巨头Blender和3ds Max一直在争夺顶级地位。 随着技术的进步和用户需求的演变&#xff0c;一个重要问题逐渐浮出水面&#xff1a;Blender是否最终会取代3ds Max&#xff1f;本文将深入探讨二者各自的优势和劣势、当前状况&…

SpringMVC使用AOP监听方法推送数据

导入aop的maven依赖 <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.6.12</version> </dependency>创建一个spring的XML文件编写aop配置 <?xml version"1.0" …

pytest+yaml实现接口自动化框架

前言 httprunner 用 yaml 文件实现接口自动化框架很好用&#xff0c;最近在看 pytest 框架&#xff0c;于是参考 httprunner的用例格式&#xff0c;写了一个差不多的 pytest 版的简易框架 项目结构设计 项目结构完全符合 pytest 的项目结构&#xff0c;pytest 是查找 test_.…

【ARM Coresight OpenOCD 系列 1 -- OpenOCD 介绍】

请阅读【ARM Coresight SoC-400/SoC-600 专栏导读】 文章目录 1.1 OpenOCD 介绍1.1.1 OpenOCD 支持的JTAG 适配器1.1.2 OpenOCD 支持的调试设备1.1.3 OpenOCD 支持的 Flash 驱动 1.2 OpenOCD 安装与使用1.2.1 OpenOCD 代码获取及安装1.2.2 OpenOCD 使用1.2.3 OpenOCD 启用 GDB…

互联网金融风控常见知识点

1.怎么做互联网金融风控 首先风险不是都是坏的&#xff0c;风险是有价值的。也就是风险的VaR值(Value at Risk) 对于互联网信贷风控&#xff0c;是要把风险和收益做到更合理的平衡&#xff0c;在控制风险水平的情况下使得收益更高。 所以&#xff0c;做风控的不是一味地追求耕…