详解自动化测试之 Selenium 与 Junit

news2024/11/24 15:49:02

文章目录

  • 1. 什么是自动化
  • 2. 自动化测试的分类
  • 3. selenium(web 自动化测试工具)
  • 4. 一个简单的自动化例子
  • 5. selenium 常用方法
    • 5.1 查找页面元素 findElement ()
    • 5.2 元素的定位 By 类
    • 5.3 xpath 路径语言
  • 6. 常见的元素操作
    • 6.1 输入文本 sendKeys
    • 6.2 点击 click
    • 6.3 提交 submit (通过回车键提交)
    • 6.4 请求 clear
    • 6.5 获取文本 getText
    • 6.6 获取属性对应的值 getAttribute
    • 6.7 获取页面的标题和 URL
  • 7. 窗口
    • 7.1 窗口大小的设置(manage().window())
    • 7.2 窗口的切换
  • 8. 屏幕截图 getScreenshotAs
  • 9. 等待
    • 9.1 强制等待
    • 9.2 隐式等待
    • 9.3 显示等待
  • 10. 浏览器导航 navigate
  • 11. 弹窗
  • 12. 选择框 select
  • 13. 执行脚本 executeScript
  • 14. 文件上传
  • 15. 浏览器的参数设置 ChromeOptions
  • 16. 单元测试工具 Junit
    • 16.1 Junit 的执行顺序
    • 16.2 参数化
    • 16.3 测试套件
  • 17. 断言 Assertions

谷歌浏览器升级到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 了。

1. 什么是自动化

作用:通过自动化测试有效减少人力的投入,同时提高了测试的质量和效率

概念:自动化测试指软件测试的自动化,在预设状态下运行应用程序或者系统,预设条件包括正常和异常,最后评估运行结果。将人为驱动的测试行为转化为机器执行的过程

比如,回归测试版本越来越多,版本回归的压力越来越大,仅通过人工测试来回归所有的版本肯定是不现实的,所以我们需要借助自动化测试

2. 自动化测试的分类

  1. 接口自动化测试
  2. UI自动化测试(界面测试)
  3. 移动端自动化测试
  4. web 端自动化测试

3. selenium(web 自动化测试工具)

(1)选择 selenium 作为的 web 自动化测试工具是因为

  1. 开源免费
  2. 支持多浏览器,比如 Chrome、Firefox、IE浏览器…
  3. 支持多系统,比如 Linux、Windows、MacOs
  4. 支持多语言,比如 Java、Python、JavaScript…
  5. selenium 包提供了很多可供测试使用的 API

(2)环境部署

如果想要使用 selenium 实施 Web 自动化测试,需要的环境是什么

Chrome 浏览器、谷歌驱动(ChromeDriver)、selenium 工具包

(3)什么是驱动?

人工测试的情况下,人来手动的打开浏览器,那么驱动就是人力

对自动化来说,代码不能够直接打开浏览器,需要借助驱动程序才能打开浏览器

selenium 编写的自动化脚本是如何打开浏览器(selenium Driver 浏览器三者之间的关系)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a7xMlbPA-1681625932504)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1673750214137.png)]

驱动要接受 selenium 脚本发送过来的 http 请求并解析

4. 一个简单的自动化例子

创建 Maven 项目,导入 selenium 包

<dependencies>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.0.0</version>
    </dependency>
</dependencies>

简单自动化示例主要包含五个步骤

  1. 创建驱动实例,创建会话(实例化 ChromeDriver 对象)
  2. 访问网站(对象.get(“网站”))
  3. 查找元素(对象.findElement(By.cssSelector(“#网址元素id”)).sendKeys(“输入内容”))
  4. 操作元素(对象.findElement(By.cssSelector(“#网址元素id”)).click())
  5. 结束会话(对象.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 huge() 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();
    }
}

5. selenium 常用方法

5.1 查找页面元素 findElement ()

参数:By 类(提供通过什么方式来查找元素)

返回值:webElemen

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3CMF6yKn-1681625784105)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1673751728162.png)]

当元素可以在页面找到的情况下,程序正常退出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fxMItxKL-1681625784106)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1673751423117.png)]

当元素在页面找不到的情况下,程序执行报错

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AJYyQUEW-1681625784106)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1673751541380.png)]

findElements()方法

参数:By 类(提供通过什么方式来查找元素)

返回值:List

public void methodTest() {
    ChromeDriver driver = new ChromeDriver();
    driver.get("https://www.baidu.com");
    driver.findElement(By.cssSelector("#kw"));
    List<WebElement> elements= driver.findElements(By.className("hotsearch-item"));
    for (WebElement element : elements) {
        System.out.println(element.getText());
    }

    driver.findElement(By.cssSelector("#su"));
    driver.quit();
}

5.2 元素的定位 By 类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pO6Lng9k-1681625784108)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1673752409013.png)]

5.3 xpath 路径语言

语法:

层级:/子级 // 跳级

属性:@

函数:contains()…

自动化里要求元素的定位必须要唯一,但是手动在页面复制 selector 或者 path 元素不一定是唯一的,需要我们进行手动修改到唯一

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q6meK5YM-1681625784109)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1673753096032.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B4LcN68A-1681625784110)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1673753516762.png)]

6. 常见的元素操作

6.1 输入文本 sendKeys

sendKeys,仅适用于文本字段和内容可编辑的元素

 // 找到百度搜索框
 WebElement ele = driver.findElement(By.cssSelector("#kw"));
// 在输入框输入文本
ele.sendKeys("qq音乐");

// 找到百度搜索框并输入文本
// driver.findElement(By.cssSelector("#kw")).sendKeys("qq音乐");

6.2 点击 click

// 3.找到百度搜索框并输入文本
driver.findElement(By.cssSelector("#kw")).sendKeys("qq音乐");

6.3 提交 submit (通过回车键提交)

submit 仅适用于表单元素,selenium 官方不推荐使用 submit,更推荐 click

// 找到百度搜索框并输入文本
driver.findElement(By.cssSelector("#kw")).sendKeys("qq音乐");
// 找到百度一下通过回车键进行提交
driver.findElement(By.cssSelector("#su")).submit();

6.4 请求 clear

clear:适用于频繁测试输入是否可以重复输入

// 清除输入框的内容
driver.findElement(By.cssSelector("#kw")).clear();

6.5 获取文本 getText

// 获取文本
String text = driver.findElement(By.cssSelector("#s-top-left > div > a")).getText();
System.out.println("获取到的文本:" + text);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5VrcD6yu-1681625784110)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1675913113054.png)]

6.6 获取属性对应的值 getAttribute

// 获取属性的值
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);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7234Ct0O-1681625784111)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1675913097007.png)]

6.7 获取页面的标题和 URL

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());

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aYOQ59T5-1681625784112)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1677659438770.png)]

7. 窗口

7.1 窗口大小的设置(manage().window())

最大化、最小化、全屏窗口、手动设置窗口大小

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();
}

7.2 窗口的切换

打开百度首页,点击图片超链接进入到百度图片首页,获取百度图片页面的 “百度一下” 按钮

	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);
        driver.findElement(By.cssSelector("#homeSearchForm > span.s_btn_wr > input"));
        driver.quit();
	}

结果报错了,找不到页面元素

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mAX8YaqV-1681625784112)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1675931056472.png)]

这是是因为,当浏览器每次打开一个标签页的时候,会自动的给每个标签页进行标识,这个叫做句柄

可以通过 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<String> 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();
    }

那么当我们打开了好几个窗口,怎么切换?

自动化基本没有这样的场景,所以这里不用考虑太多

8. 屏幕截图 getScreenshotAs

这里需要在 pom.xml 中引入屏幕截图文件需要用到的包

    <!-- 保存屏幕截图文件需要用到的包-->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>

需要注意的一点是,当代码执行到查找结果页面元素的时候,页面还没有加载完全,此时程序执行的速度是比,页面渲染的速度更快的,所以要注意在代码中添加等待机制,让页面先渲染一下,再截图

    public void windowConTrol() throws InterruptedException, IOException {
        // 屏幕截图
        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 = "my.png";
        FileUtils.copyFile(srcfile,new File(filename));
        driver.findElement(By.cssSelector("#content_left"));
        driver.quit();
    }

我这里的代码文件名为固定格式,如果程序多次执行生成的图片文件会被同名覆盖,这就可以将文件名的命名添加动态数据(时间戳)

9. 等待

程序执行的速度要比浏览器渲染的速度要快很多

四种等待:强制等待、隐式等待、显示等待、流畅等待

需要注意:显示等待、隐式等待,不能同时使用,同时使用可能会出现意想不到的等待结果

9.1 强制等待

在 8. 屏幕截图时,为了让页面渲染完全后才进 行屏幕截图,中间进行了等待 3s (Thread.sleep())

这个就会使 程序阻塞进行,这种方式在自动化测试中会用到,但用的不是特别多,这是因为

每一个自动化方法就是一个自动化测试用例,比如一个用例需要 10s,100测试用例 1000s,200个用例 2000s,这样耗费时间太多了,只能接受十几秒或几分钟内

9.2 隐式等待

隐式等待会作用于 driver 的整个生命周期

隐式等待会一直轮询判断元素是否存在,如果不存在就等待设置好的时间里不断的进行轮询,直到元素能够被找到

public class autoTest {
    ChromeDriver driver = new ChromeDriver();
    public void waitContro() {
        // 添加隐式等待
        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();
    }
}

9.3 显示等待

public class autoTest {

    ChromeDriver driver = new ChromeDriver();
    public void webDriverWait() {
        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();
    }
}

10. 浏览器导航 navigate

浏览器的前进(forward)、后退(back)、刷新(refresh)

public class autoTest {
    ChromeDriver driver = new ChromeDriver();
    // 浏览器导航
    public void navigateConTrol() {
        driver.get("https://www.baidu.com");
//        driver.navigate().to("https://www.baidu.com");
        // 想要回退到访问百度网址之前的状态
        driver.navigate().back();
        // 前进 进入到百度首页
        driver.navigate().forward();
        // 刷新百度首页
        driver.navigate().refresh();
        driver.quit();
    }
}

11. 弹窗

弹窗的类型:警告弹窗、确认弹窗、提示弹窗

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SnxcZflR-1681625784113)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1677663831186.png)]

处理弹窗的步骤:

  1. 将 driver 对象作用到弹窗上(切换到弹窗) driver.switchTo.alert()
  2. 选择确认 accept() / 取消 dismiss() (提示弹窗 输入文本 sendkeys 在页面上是看不到输入文本的执行效果的

虽然警告弹窗只有确认按钮,但 accept 和 dismiss 都能处理

虽然警告弹窗和确认弹窗都没有输入文本的地方,但如果要执行 alert.sendKeys 代码,也是不会报错的

ChromeDriver chromeDriver = new ChromeDriver();
// 提示弹窗
void Alertcontro() throws InterruptedException {
    chromeDriver.get("file:///D:/%E6%8F%90%E7%A4%BA%E5%BC%B9%E7%AA%97.html");
    Thread.sleep(3000);
    // 打开弹窗
    chromeDriver.findElement(By.cssSelector("body > input[type=button]")).click();
    Thread.sleep(3000);
    // 切换到弹窗进行弹窗处理
    Alert alert = chromeDriver.switchTo().alert();
    Thread.sleep(3000);
    // 1. 输入
    alert.sendKeys("666");
    Thread.sleep(3000);
    // 2. 点击确认
    alert.accept();
    Thread.sleep(3000);
    // 取消
    alert.dismiss();
    chromeDriver.quit();
}

12. 选择框 select

选项的选择方式:根据文本选择(selectByVisibleText)、根据属性值选择(selectByValue)、根据序号选择(selectByIndex)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PLExhyww-1681625784115)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1677666804934.png)]

ChromeDriver chromeDriver = new ChromeDriver(); 
void selectControll() throws InterruptedException {
        chromeDriver.get("file:///D:/%E9%80%89%E6%8B%A9%E6%A1%86.html");
        WebElement ele = chromeDriver.findElement(By.cssSelector("#ShippingMethod"));
        Thread.sleep(2000);
        // 先创建选择框对象
        Select select = new Select(ele);
        Thread.sleep(2000);
        // 根据文本来选择
//        select.selectByVisibleText("333");
        // 根据属性值选择
//        select.selectByValue("222");
        // 根据序号选择【序号从 0 开始】
        select.selectByIndex(3);
        Thread.sleep(2000);
        chromeDriver.quit();
    }

13. 执行脚本 executeScript

executeScript(参数:JS)

ChromeDriver chromeDriver = new ChromeDriver();
void scriptControll() throws InterruptedException {
    chromeDriver.get("https://image.baidu.com/");
    Thread.sleep(3000);
    // 执行 JS 命令:让页面置顶/置底
    chromeDriver.executeScript("document.documentElement.scrollTop=500");
    Thread.sleep(3000);
    chromeDriver.executeScript("document.documentElement.scrollTop=0");
    Thread.sleep(3000);
    chromeDriver.quit();
}

// 也可以通过 JS 代码来操作在输入框中搜索
void scriptControll() throws InterruptedException {
     chromeDriver.get("https://www.baidu.com");
     // 找到百度搜索框,输入 “迪丽热巴”
     chromeDriver.executeScript("var ss = document.querySelector(\"#kw\");ss.value = '迪丽热巴';");
     Thread.sleep(3000);
     chromeDriver.quit();
}

14. 文件上传

ChromeDriver driver = new ChromeDriver();
// 文件上传
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:\\微信图片_20230212212832.jpg");
    Thread.sleep(3000);
    driver.quit();
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KiaCGl5m-1681625784115)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1677810737509.png)]

15. 浏览器的参数设置 ChromeOptions

无头模式:在实际工作中,测试人员将自动化部署在机器上自动的执行,测试人员看不到测试过程,而是直接查看自动化执行的结果

有头模式:就是程序在自动的测试,我们是可以看到执行测试的过程界面

浏览器的参数设置需要在创建浏览器对象之前

void paramsControll() {
    // 先创建选项对象,然后再设置浏览器参数
    ChromeOptions options = new ChromeOptions();
    options.addArguments("-headless");
    // 百度搜索迪丽热巴
    ChromeDriver driver = new ChromeDriver(options);
    driver.get("https://www.baidu.com");
    driver.findElement(By.cssSelector("#kw")).sendKeys("迪丽热巴");
    driver.findElement(By.cssSelector("#su")).click();
    driver.quit();
}

16. 单元测试工具 Junit

自动化就是 selenium 脚本来实现的,junit 是 java 的单元测试工具,只不过在实现自动化的时候需要借用一下 junit 库里面提供的一些注解(junit5)

<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-suite</artifactId>
    <version>1.8.2</version>
    <scope>test</scope>
</dependency>

@Test(测试方法)、@BeforeEach(每个测试用例前执行一次)、@BeforeAll(所有测试用例前执行一次)、 @AfterEach(每个测试用例之后执行一次)、@AfterAll(所有测试用例之后执行一次)

并且 BeforeAll 和 AfterAll 注解的方法必须为静态方法

(1)注解

junit 中提供了注解功能

@Test 表示方法是测试方法,执行当前这个类时,会自动的执行该类下所有带 @Test 注解的用例

public class junitTest {
    @Test
    void bbb() { System.out.println("bbbb");}
    @Test
    void ccc() { System.out.println("cccc");}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FKPKNljW-1681625784116)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1676107787749.png)]

@BeforeEach 表示当前的方法需要在每个用例执行之前都执行一次

public class junitTest {
    @BeforeEach
    void aaa() {System.out.println("aaaa");}
    
    @Test
    void bbb() {System.out.println("bbbb");}

    @Test
    void ccc() {System.out.println("cccc");}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-75ZNi6mX-1681625784117)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1676107758523.png)]

@BeforeAll 当前的方法需要在当前类下所有用例之前执行一下,被该注解修饰的方法必须为静态方法

public class junitTest {
    @BeforeAll
    static void aaa() {System.out.println("aaaa");}
    
    @Test
    void bbb() {System.out.println("bbbb");}

    @Test
    void ccc() {System.out.println("cccc");}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aPcLVZDd-1681625784117)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1676107976344.png)]

@AfterEach 在每个用例执行之后都要执行一次

public class junitTest {
    @AfterEach
    void aaa() {System.out.println("aaaa");}
    
    @Test
    void bbb() {System.out.println("bbbb");}

    @Test
    void ccc() {System.out.println("cccc");}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7tOrgOg1-1681625784118)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1676108056007.png)]

@AfterAll

public class junitTest {
    @AfterAll
    static void aaa() {System.out.println("aaaa");}
    
    @Test
    void bbb() {System.out.println("bbbb");}

    @Test
    void ccc() {System.out.println("cccc");}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7AmenVlV-1681625784120)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1676108097252.png)]

16.1 Junit 的执行顺序

注意看两次代码的执行顺序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-34ugmF0R-1681625784121)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1677814648215.png)]

可以看到测试用例的执行并不会按照我们编写测试用例的顺序来执行,那么这就会出现一些问题

比如说对博客的登录系统编写测试用例,用例包含:

  1. 检查登录页面展现是否正确
  2. 检查正常登录 (跳转到博客首页 / 列表页)
  3. 异常登录

执行顺序的问题,就会导致比如说,先执行步骤二,那么此时是登录成功的,页面就会跳转,然后再执行步骤一就会 报错

1. 通过 order 注解来排序

  • 先使用注解说明当前类下所有的用例需要使用 order 注解来进行排序,注解该注解必须要使用到类上
  • 然后通过 Order 来指定用的执行具体顺序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dnAd5Ler-1681625784121)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1678190744599.png)]

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class JunitTest {
    @Test
    @Order(1)
    void ediloginTest() {
        System.out.println("loginTest");
    }

    @Test
    @Order(2)
    void AindexTest() {
        System.out.println("indexTest");
    }
    
    @Test
    @Order(3)
    void editTest() {
        System.out.println("editTest");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NqwWttF1-1681625784122)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1678190295598.png)]

16.2 参数化

尽可能的通过一个用例,多组参数来模拟用户的行为

单参数:

@ParameterzedTest + @ValueSource(数据类型方法/加s = {参数1,参数2,参数3,…})

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vk7D0aFe-1681625784123)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1678191635490.png)]

多参数:

@parameterizedTest + @CsvSource({“”, “”, '", …}) 每个双引号就是一组测试用例

@ParameterizedTest
@CsvSource({"张三,22","李四,25","王五,35"})
void muchParamsTest(String name,int age) {
    System.out.println("name: " + name + ",age: " + age);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mc6tOC6D-1681625784123)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1678192053809.png)]

多参数(从第三方 csv 文件读取数据源)

@ParameterizedTest + @CsvFileSource(files = “文件路径+名字”)

这里的这个 csv 文件,不要直接改后缀生成,要用系统自带的 Excel 工具,来打开和编辑 csv 文件

@ParameterizedTest
@CsvFileSource(files = "D:\\mycsv.csv")
void csvfileParamsTest(String name, int age) {
    System.out.println("name: " + name + ",age: " + age);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NHpxTQgn-1681625784123)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1678193821094.png)]

driver.navigate().back();

这个是模拟了浏览器的后退按钮,使得当前页面返回到上一个页面。这个方法可以用于测试中,例如在测试过程中需要回到之前的页面重新执行某些操作或者验证某些信息。

动态参数方法

// 通过动态方法来提供数据源
@ParameterizedTest
@MethodSource("methodParams")
void dynamicMethodParamsTest(String name,int age) {
    System.out.println("name: " + name + ",age: " + age);
}
static Stream<Arguments> methodParams() throws InterruptedException {
    // 构造动态参数
    String[] arr = new String[5];
    for (int i = 0; i < arr.length; i++) {
        Thread.sleep(500);
        arr[i] = System.currentTimeMillis() + "";
    }
    return Stream.of(
            Arguments.arguments(arr[0],20),
            Arguments.arguments(arr[1],20),
            Arguments.arguments(arr[2],20),
            Arguments.arguments(arr[3],20),
            Arguments.arguments(arr[4],20)
    );
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A4Iv1Jnb-1681625784124)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1678195006408.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QshfXEiA-1681625784125)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1678195189267.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IWoyEzkI-1681625784125)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1678195447837.png)]

16.3 测试套件

创建三个类,给每个类中都加上测试注解 @Test,如果要测试运行,只能一个类一个类运行,不能对三个类同时运行,

所以可以使用测试套件来同时运行多个测试类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ot48ktbx-1681625784126)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1678195913441.png)]

创建一个类,通过 @Suite 注解标识该类为测试套件类(而不是测试类)

  1. 指定类来运行用例(要运行的用例必须要被 @Test 注解,除了参数化的用例)
/**
 * @Description: 测试套件
 * @Date 2023/3/7 21:29
 */
@Suite
@SelectClasses({aaa.class,bbb.class,ccc.class})
public class runSuite {
}

运行程序可以看到

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-03cQdssN-1681625784126)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1678196064853.png)]

  1. 指定包名来运行(第一种方法,如果类特别多的情况下,不太适合,可以指定包)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g1lLvtDL-1681625784127)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1678196566092.png)]

@Suite
@SelectPackages("com.autoTest0303")
public class runSuite {
}

17. 断言 Assertions

断言匹配 assertEquals,断言不匹配 assertNotEquals

@Test
void huixiang() {
    ChromeDriver driver = new ChromeDriver();
    driver.get("https://www.baidu.com");
    String text = driver.findElement(By.cssSelector("#su")).getAttribute("value");//百度一下
    // 假如这里获取的属性不是百度一下,而是百度两下
    System.out.println(text);
    Assertions.assertEquals("百度两下",text);
    driver.quit();
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gYTafCz7-1681625784140)(C:\Users\28463\AppData\Roaming\Typora\typora-user-images\1676108848359.png)]

断言结果为真 assertTrue,断言结果为假 assertFalse

@Test
void ddd() {
    Assertions.assertTrue(1==1);//正确
}
@Test
void eee() {
    Assertions.assertFalse(1==1);//报错
}
@Test
void fff() {
    Assertions.assertFalse(1==0);//正确
}

断言结构为空 assertNull,断言结果不为空 assertNotNull

@Test
void ggg() {
    String aaa = null;
    Assertions.assertNull(aaa);//通过
}
@Test
void hhh() {
    Assertions.assertNotNull("你好");//通过
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是Android FrameWork,请你介绍一下?

Framework是什么 Framework的中文意思是“框架”&#xff0c;在软件开发中通常指开发框架&#xff0c;在一个系统中处于内核层之上&#xff0c;为顶层应用提供接口&#xff0c;被设计用来帮助开发者快速开发顶层应用&#xff0c;而不必关心系统内核运行机制&#xff0c;通常Fr…

zabbix报警配置

一、前言 这里用的是zabbix6.0LTS版本&#xff0c;这里记录自定义配置报警&#xff0c;因为邮件报警基本已经很少有人使用了&#xff0c;大部分是&#xff0c;短信、飞书、钉钉等等工具&#xff0c;所有需要定制化报警 二、定义脚本存放路径 cd /usr/local/zabbix/etc[rootn…

MODBUS 转 EtherNet/IP 网关连接希望森兰变频器案例

Modbus转Ethernet/Ip网关&#xff0c;用于将多个 MODBUS 从站设备接入 ETHERNET/IP 主站网络&#xff0c;实现 MODBUS 转 ETHERNET/IP 功能。配上 MODBUS 转 EtherNet 网关专用的 EDS 文件,实现 ETHERNET/IP 主 站对 MODBUS 从站设备的控制。 需要设备 .24v电源模块 罗克韦尔PL…

【城市污水处理过程中典型异常工况智能识别】(基于迁移学习,拓扑结构卷积神经网络的污水异常工况识别)

基于迁移学习拓扑结构卷积神经网络的污水异常工况识别 **摘 要&#xff1a;针对城市污水处理过程的异常工况识别问题&#xff0c;本文提出了基于图像纹理性分析的工况识别方法。首先总结了几种典型的异常工况的特点&#xff0c;并且分析了卷积神经网络特征提取异常工况的几种纹…

月薪20k的性能测试必备技能:发现性能瓶颈掌握性能调优

背景 当下云计算、大数据盛行的背景下&#xff0c;大并发和大吞吐量的需求已经是摆在企业面前的问题了&#xff0c;其中网络的性能要求尤为关键&#xff0c;除了软件本身需要考虑到性能方面的要求&#xff0c;一些硬件上面的优化也是必不可少的。 作为一名测试工作者&#xf…

ubuntu将主文件夹的文件夹中文名称改为英文

许多人在使用ubuntu时使用汉语的&#xff0c;但是主文件夹下的文件夹也随之变成了中文&#xff0c;导致命令行下输入文件夹名称非常的困难&#xff0c;那么怎么简单的把名字改成英文的呢&#xff1f;&#xff08;也不知道哪个版本开始不出现下面这个图示提示了&#xff09; 方法…

Vue2-黑马(十二)

目录&#xff1a; &#xff08;1&#xff09;vue2-登录-store-user.js &#xff08;2&#xff09;实战-登录-store-user.js &#xff08;3&#xff09;登录-实战--permission.js-获取角色 &#xff08;1&#xff09;vue2-登录-store-user.js 我们进入store中的actions查看它…

MySQL - 基于SSL安全连接的主从复制

目录 &#x1f341;主从复制的原理 &#x1f341;部署master &#x1f341;部署slave &#x1f341;测试SSL主从复制 &#x1f990;博客主页&#xff1a;大虾好吃吗的博客 &#x1f990;MySQL专栏&#xff1a;MySQL专栏地址 生产环境中一台mysql主机存在单点故障&#xff0c;所…

c/c++:二维数组,数组的行数和列数求法sizeof,数组初始化不同形式,5个学生,3门功课,求学生总成绩和功课总成绩

c/c&#xff1a;二维数组&#xff0c;数组的行数和列数求法sizeof&#xff0c;数组初始化不同形式&#xff0c;5个学生&#xff0c;3门功课&#xff0c;求学生总成绩和功课总成绩 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#x…

【从零开始学Skynet】实战篇《球球大作战》(十一):测试登录流程

终于可以测试work协议了。只要走得通&#xff0c;就代表完成了整套底层框架。 1、主服务修改 我们重新修改主服务&#xff0c;让它智能一些&#xff0c;根据配置文件自动开启服务&#xff0c;无须手动设置。如下代码所示&#xff1a; local skynet require "skynet"…

Linux应用编程(信号基础)

一、基本概念 信号是事件发生时对进程的通知机制&#xff0c;也可以把它称为软件中断。信号与硬件中断的相似之处在于能够打断程序当前执行的正常流程&#xff0c;其实是在软件层次上对中断机制的一种模拟。大多数情况下&#xff0c;是无法预测信号达到的准确时间&#xff0c;…

录屏剪辑软件哪个好 录屏后怎么剪辑视频

​ 现在很多人都会通过录屏的方式来传播分享内容&#xff0c;但是很多录屏软件的操作不太方便&#xff0c;给录制带来困难。再加上很多视频在录制后需要剪辑&#xff0c;加大了视频制作的工作量&#xff0c;所以找到一款好用的录屏剪辑软件很重要。今天就来分享一下录屏剪辑软件…

从0-1优化C++类对象创建资源消耗 (附源码)

C++常用功能源码系列 文章目录 C++常用功能源码系列前言一、C++几种常用的函数是什么?二、优化过程1.源代码2.源代码总结前言 本文是C/C++常用功能代码封装专栏的导航贴。部分来源于实战项目中的部分功能提炼,希望能够达到你在自己的项目中拿来就用的效果,这样更好的服务于…

Spring MVC 配置(10)

目录 简介&#xff1a; 传统方式&#xff1a; 纯注解方式 1. Tomcat加载Servlet 2. 参数分析 3. 调用onStartup方法 注解方法替换配置的 xml 文件 简介&#xff1a; Spring MVC是Spring的一个子模块&#xff0c;也是我分析的Spring源码的最后一个模块。下面看一下Spring …

2023年安全岗面试题及经验分享

如果你正在面试安全岗&#xff0c;那么恭喜你及时看到了这篇文章~ 写在前面 本篇为大家整理了上百道网络安全面试题&#xff0c;主要方向有 网络基础、渗透测试、安全工具 等&#xff0c;其中还包括 HVV面试、CISP备考 等&#xff0c;希望在求职期可以帮到大家​&#xff01;…

WAF绕过信息收集

WAF绕过-信息收集之反爬虫延时代理池技术 思维导图 WAF拦截会出现在安全测试的各个层面&#xff0c;掌握各个层面的分析和绕过技术最为关键。 webpathbrute工具 一个Web目录扫描暴力探测工具 WebPathBrute-Web路径暴力探测工具下载&#xff1a;https://github.com/7kbstorm…

QN88封装国产FPGA

QN88GW1N-9管脚名GW2A-18管脚名AL3S10EG4S201VCCVCCIO_L1_1VCC_12VSSVSSIO_L2_1IO_L1_13IOL2AVCCO7IO_L3_1,MOSI,D1IO_L2_14IOL5A/JTAGSEL_N/LPLL_T_inIOL7A/LPLL1_T_inIO_L4_1IO_L1N_15IOL11A/TMSIOR25B/TMSIO_L5_1,SPICSNIO_L1P_16IOL11B/TCKIOR26A/TCKINITNGND7IOL12B/TDIIO…

爬虫日常练习-selenium登录12306

文章目录前言页面分析代码设计前言 hello&#xff0c;好兄弟们。经过前面几篇文章后&#xff0c;想必小伙伴们对于简单的网页文本爬取&#xff0c;图片爬取类的内容已经熟练掌握了。今天我们开始练习一个新的内容&#xff1a;selenium。有关这一块的基础知识网上太多了&#x…

Java面试题总结 | Java面试题总结4-多线程模块(持续更新)

多线程 线程互斥和线程同步 线程互斥&#xff1a;当多个线程需要访问同一资源时&#xff0c;要求在一个时间段内只能允许一个线程来操作共享资源&#xff0c;操作完毕后别的线程才能读取该资源&#xff0c;这叫线程的互斥。我们需要使用synchronized来给共享区域加锁&#xf…

腾讯云服务器CVM标准型S5和S4的区别

腾讯云服务器CVM标准型S5和S4有什么区别&#xff1f;标准型S5云服务器次新一代的云服务器&#xff0c;CPU采用2.5GHz主频的Intel Xeon Cascade Lake 或者 Intel Xeon Cooper Lake 处理器&#xff0c;睿频3.1GHz&#xff0c;目前标准型S5云服务器活动比较多&#xff0c;标准型S4…