当前位置: 首页 > news >正文

【测试开发篇9】Junit框架

目录

一、认识Junit框架

Junit和Selenium的关系是什么

导入Junit框架+common-io包

二、Junit框架的使用

2.1Junit有哪些常用注解

2.1.1@Test注解

2.1.2BeforeEach

2.1.3@BeforeAll

2.1.4@AfterAll

2.1.5@AfterEach

2.2Junit的断言

Assertions.assertEquals(期待值,真实值);

2.2.1Assertions.assertNotEquals("百度一下",text)

2.2.2Assertions.assertTrue(text.equals("百度一下"))

2.2.3Assertions.assertNull(a);

三、用例的执行顺序

①针对方法的排序

为什么需要用到juit的排序功能

四、测试套件(Suit)

@Suite

@SelectClasses({待测试的类.class})

@SelectPackages("包名")

五、参数化

5.1@ParameterizedTest、@ValueSource(strings = {})

5.2@CsvSource(value={"第一组数据","第二组数据"})

 如果参数当中包含逗号:",",就需要使用单引号转义字符串

5.3读取文件参数:@CsvFileSource(resources="/文件名称")

 5.3.1读取其他磁盘文件的操作:指定文件为files=...

5.4动态参数(单参数版本)

5.5动态参数(多参数版本)

六、对于重要测试场景的截图

第一步:定位到需要的页面

第二步:调用getSrceenshotAs方法,传入的擦参数是OutputTpye.FILE;

第三步:新建一个File类,指定路径;

第四步:调用copyFile方法,把生成的文件放到指定的目录当中


一、认识Junit框架

Junit是一个开源的Java语言的单元测试框架

回顾一下,单元测试就是在编码阶段,一般情况下,由开发进行的测试。

Junit和Selenium的关系是什么

      Junit是单元测试框架,而selenium是web自动化测试框架。如果把selenium比作灯泡,那么junit就是电灯。因此:一般情况下,junit负责运行selenium脚本编写的代码。


导入Junit框架+common-io包

<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.8.1</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>${junit.version}</version><scope>test</scope></dependency><dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-suite</artifactId><version>1.8.2</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-params</artifactId><version>5.8.2</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>${junit.version}</version><scope>test</scope></dependency>

二、Junit框架的使用

2.1Junit有哪些常用注解

2.1.1@Test注解

       这一个注解作用于方法上面,表示这个方法是一个测试用例。当@Test注解作用在一个方法上面的时候,表示这一个方法是可以直接运行的,无需通过main方法来调用


2.1.2BeforeEach

在执行每一个被@Test修饰的方法之前,都会执行一次@BeforeEach注释的方法。

@BeforeEachvoid aaa(){System.out.println("pre");}@Testvoid bbb(){System.out.println("bbb");}@Testvoid ccc(){System.out.println("ccc");}

 每执行一个@Test之前,就需要执行一次@BeforeEach注释的方法

运行类上面的运行按钮:


2.1.3@BeforeAll

       首先,被@BeforeAll注释的方法一定是静态的。

       其次,不同于@BeforeEach的是,@BeforeAll注释的方法一定是静态的,并且只会在加载外部类的时候执行一次,并不会在每一个方法执行之前再次执行了。

public class Test1 {@BeforeAllstatic void aaa(){System.out.println("pre");}@Testvoid bbb(){System.out.println("bbb");}@Testvoid ccc(){System.out.println("ccc");}
}


2.1.4@AfterAll

被这个注解修饰的方法也必须是静态的,在每一个@Test之后进行修饰。

public class Test1 {@BeforeAllstatic void aaa(){System.out.println("pre");}@Testvoid bbb(){System.out.println("bbb");}@Testvoid ccc(){System.out.println("ccc");}@AfterAllstatic void afterAll(){System.out.println("end...");}
}

运行结果:


2.1.5@AfterEach

同理,在每一个@Test注释的方法执行结束的末尾,都会执行一次@AfterEach注释的方法。

public class Test1 {@BeforeEachvoid aaa(){System.out.println("pre");}@Testvoid bbb(){System.out.println("bbb");}@Testvoid ccc(){System.out.println("ccc");}@AfterEachvoid afterAll(){System.out.println("end...");}
}

运行结果:


2.2Junit的断言

写自动化测试,结果要么是成功的,要么是失败的,不存在成功一半的情况。

那么就需要使用到断言:assert,断言预期结果真实结果是否一致。

Assertions.assertEquals(期待值,真实值);

期待值真实值一致的时候,这个断言才不会抛出异常

期待值真实值不一致的时候,就会抛出异常;


代码实现:

public class Test2 {FirefoxDriver driver;@BeforeEachpublic void get(){driver=new FirefoxDriver();//捕捉到这一个页面driver.get("https://www.baidu.com");}@Testpublic void testOne(){//尝试获取"百度一下"的文本框String text=driver.findElement(By.cssSelector("#su")).getAttribute("value");//使用AssertEquals来进行断言Assertions.assertEquals("百度一下",text);}@AfterEachpublic void after(){driver.quit();}
}

如果运行的结果一致,那么就提示测试用例通过:


2.2.1Assertions.assertNotEquals("百度一下",text)

与Assertions.assertEquals(期待值,真实值)相反。

只有不一致的时候,测试用例才会通过。


2.2.2Assertions.assertTrue(text.equals("百度一下"))

传入的参数应该是一个返回值为boolean类型的表达式

@Test
public void assertTrueTest(){String text=driver.findElement(By.cssSelector("#su")).getAttribute("value");//如果返回true,那么测试用例通过,否则测试用例不通过Assertions.assertTrue(text.equals("百度一下"));}

同理,还有AssertFalse 


2.2.3Assertions.assertNull(a);

 @Testpublic void assertNull(){String a=null;Assertions.assertNull(a);}

如果一个引用为null,那么默认测试用例通过。

同理,还有Assertions.assertNotNull(),那么一个引用不为null的时候,测试用例才通过。


三、用例的执行顺序

①针对方法的排序

第一步:在这个类上面添加注解:@TestMethodOrder(MethodOrderer.OrderAnnotation.class)


第二步:

使用@Order(执行顺序)作用在方法上面,表示是第几个执行;


@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class Test2 {FirefoxDriver driver;@BeforeEach@Order(1)public void get(){driver=new FirefoxDriver();//捕捉到这一个页面driver.get("https://www.baidu.com");}@Test@Order(2)public void testOne(){//尝试获取"百度一下"的文本框String text=driver.findElement(By.cssSelector("#su")).getAttribute("value");Assertions.assertNotEquals("百度一下",text);}@Test@Order(3)public void assertTrueTest(){String text=driver.findElement(By.cssSelector("#su")).getAttribute("value");//如果返回true,那么测试用例通过,否则测试用例不通过Assertions.assertTrue(text.equals("百度一下"));}@AfterEachpublic void after(){driver.quit();}
}

为什么需要用到juit的排序功能

       如果用例之间存在关联关系(存在耦合)(但是不是绝对有关联关系),那么就需要手动指定用例的执行顺序。因为各个测试用例的执行顺序是无序的。

       这样就可以避免出现各个测试用例之间执行顺序不正确的情况。


四、测试套件(Suit)

测试套件,用于把所有的测试用例都执行起来。

@Suite

这一个注解作用于类上面,用于执行所有的测试用例


@SelectClasses({待测试的类.class})

这个注解和上面的注解需要配合使用,这样才可以一起执行待测试类的测试用例。

当然也可以传递多个.class对象。


@Suite
@SelectClasses({Test1.class,Test2.class})
public class SuitTest {}

运行结果:


@SelectPackages("包名")

扫描这一个包下面包含了@Test注解的方法的类

@Suite
@SelectPackages("TestFile")
public class SuitTest {}

但是扫描的包不可以和当前的类在同一个包下面;

需要注意的是,这种情况下面,被扫描的类一定是xxxTest这样命名的,否则是扫描不到的。


五、参数化

对于一个测试用例,可能会测试传入的参数是多种的情况;

例如对于一个文本框进行测试,可以测试多种输入的情况

如下图:如果为每一个输入的name都定义一个方法,那么就显得非常冗余,于是就引入了参数化。


5.1@ParameterizedTest、@ValueSource(strings = {})

第一个注解@Parameterized作用在方法上面,用来表示这个方法支持传入多个参数;

第二个注解@ValueSource用于指定传入参数的类型;例如:strings={}就表示传入的是一个string类型的数组;

ints={2,3,4,5}表示传入的参数是一个int类型的数组;

但是,同一个@ValueSource注解当中只支持一种数据类型

运行结果:


5.2@CsvSource(value={"第一组数据","第二组数据"})

其中,每一组数据当中对应方法传入的参数的值。采用","来分割。 

@ParameterizedTest@CsvSource(value = {"小明,20","小红,30","小李,40"})public void printStringAndInteger(String name,int age){System.out.println("name:"+name+";age="+age);}


当然,一组数据当中的分隔符也不一定采用系统默认的","分割,也可以采用自定义的分隔符。

@ParameterizedTest@CsvSource(value = {"小明-20","小红-20","小李-40"},delimiter = '-')public void printStringAndAge(String name,int age){System.out.println("name:"+name+";age="+age);}

用户自定义的分隔符: 


 如果参数当中包含逗号:",",就需要使用单引号转义字符串


5.3读取文件参数:@CsvFileSource(resources="/文件名称")

第一步:在resources目录下面新建一个文件,并且指定名称;

第二步:在文件当中以逗号的方式分割每一组参数;

然后运行程序:


 5.3.1读取其他磁盘文件的操作:指定文件为files=...

    @ParameterizedTest@CsvFileSource(files = "E:\\OJSystem\\src\\main\\resources\\my.csv")public void printStringAndAge3(String name,int age){System.out.println("name:"+name+";age="+age);}

5.4动态参数(单参数版本)

第一步:定义提供数据的方法,必须声明为静态;返回值为一个Stream对象;方法内部调用Stream.of(参数列表);

第二步:定义dyNatickTest(String x)方法获取参数;并用@MethodSource()指定

第三步:输出参数。

@ParameterizedTest@MethodSource("methodDemo")void dyNatickTest(String x){System.out.println(x);}static Stream<String> methodDemo(){return Stream.of("张三","李四","王五");}

如果@MethodSource当中不指定参数的名称,那么就会调用跟测试用例同名的静态方法


5.5动态参数(多参数版本)

第一步:新建一个测试方法,并且指定多个参数。使用@ParameterizedTest和@MethodSource注解同时作用

第二步:新建一个和测试用例同名的静态方法;

第三步:在静态方法当中调用Stream.of()方法,并且传入的参数为多个Arguments.arguments(第一步创建方法的参数列表)


 代码实现:

@ParameterizedTest@MethodSourcevoid paramsTest(String name,int age){System.out.println("name:"+name+";age :"+age);}/*** 多参数的版本* Stream对象@return*/static Stream<Arguments> paramsTest(){return Stream.of(Arguments.arguments("lucy",29),Arguments.arguments("lili",30),Arguments.arguments("lisi",40));}

六、对于重要测试场景的截图

第一步:定位到需要的页面

第二步:调用getSrceenshotAs方法,传入的擦参数是OutputTpye.FILE;

第三步:新建一个File类,指定路径;

第四步:调用copyFile方法,把生成的文件放到指定的目录当中

@Testpublic void screenShortTest() throws IOException, InterruptedException {//百度搜索关键字driver.findElement(By.cssSelector("#kw")).sendKeys("selenium");driver.findElement(By.cssSelector("#su")).click();//屏幕截图,把截图的文件存放到指定的位置//以文件的形式存储File srcFile=driver.getScreenshotAs(OutputType.FILE);//把截图的文件存放到指定的目录下面File destFile=new File("E:/OJSystem/src/test/Files/img.png");Thread.sleep(1000);FileUtils.copyFile(srcFile,destFile);}

相关文章:

【测试开发篇9】Junit框架

目录 一、认识Junit框架 Junit和Selenium的关系是什么 导入Junit框架common-io包 二、Junit框架的使用 2.1Junit有哪些常用注解 2.1.1Test注解 2.1.2BeforeEach 2.1.3BeforeAll 2.1.4AfterAll 2.1.5AfterEach 2.2Junit的断言 Assertions.assertEquals(期待值&#…...

《Spring MVC》 第五章 实现RESTful

前言 教授大家如何实现RESTful 1、什么是RESTful resource Representational State Transfer 的缩写&#xff0c;就是“表现层资源表述状态转移” 1.1、Resource&#xff08;资源&#xff09; web应用的文件&#xff0c;uri定位 1.2、Representation&#xff08;资源的描…...

Last Week in Milvus

What’s New Core Updates #23353 在 2.3 版本中&#xff0c; milvus 和 knowhere 引擎会移除了 Annoy 索引。Annoy 索引在性能和召回率方面均不如 IVF、HNSW 等索引&#xff0c;维护成本比较高所以经过讨论决定在 2.3 中移出 Annoy 索引的支持&#xff0c;有使用的用户要注意…...

Cursor IDE一个GPT4人工智能自动程序编辑器

让我们来了解一下Cursor IDE是什么。Cursor IDE是一个新型的编程工具&#xff0c;可以通过它生成、编辑以及与人工智能进行交互分析代码。官方网站上的三个单词“Build Software. Fast.”&#xff08;快速构建软件&#xff09;以及“Write, edit, and chat about your code wit…...

PPO算法-理论篇

1. Policy Gradient 【李宏毅深度强化学习笔记】1、策略梯度方法&#xff08;Policy Gradient&#xff09; 李宏毅深度强化学习-B站 2. PPO PPO 算法 PPO算法更新过程如下&#xff1a; 初始化policy参数 θ 0 \theta^0 θ0在每一步迭代中&#xff1a; 使用 θ k \theta^k …...

【现货】AP6317 同步3A锂电充电芯片 带短温度保护

AP6317是一款面向5V交流适配器的3A锂 离子电池充电器。它是采用800KHz固定频率的同 步降压型转换器&#xff0c;因此具有高达92%以上的充电效 率&#xff0c;自身发热量极小。 包括完整的充电终止电路、自动再充 电和一个精确度达1%的4.2V预设充电电压&#xff0c;内 部集成了防…...

MyBatis详解(2)

8、自定义映射resultMap 8.1、resultMap处理字段和属性的映射关系 若字段名和实体类中的属性名不一致&#xff0c;则可以通过resultMap设置自定义映射 <!--resultMap&#xff1a;设置自定义映射属性&#xff1a;id&#xff1a;表示自定义映射的唯一标识type&#xff1a;查询…...

2023-04-14 使用纯JS实现一个2048小游戏

文章目录 一.实现思路1.2048的逻辑2.移动操作的过程中会有三种情况 二.代码部分:分为初始化部分和移动部分1.初始化部分1.1.生成第一个方块:1.2.生成第二个方块: 2.移动过程部分: 三.实现代码1.HTML部分2.CSS部分3.JS部分3.1.game对象的属性3.2.game对象的start方法3.3.game对象…...

C++入门(3)

C入门 1.auto关键字&#xff08;C11&#xff09;1.1. 类型别名的思考1.2. auto简介1.3. auto使用情景1.4. auto的使用细则1.5. auto不能推导的场景 1.auto关键字&#xff08;C11&#xff09; 1.1. 类型别名的思考 随着程序越来越复杂&#xff0c;程序中用到的类型也越来越复杂…...

【亲测有效】更新了WIN11之后 右键无 新建WORD,PPT,EXCEL 选项 问题 解决方案

原本正常的正版系统&#xff0c;在昨天4月自动更新安装之后&#xff0c;发现右键找 不到新建文档了&#xff0c;word,ppt,excel都不见了。 看了网上大神的方法 Win11安装了Office右键没有新建Excel选项怎么办&#xff1f; - 知乎 可以解决一部分 官方解决方案&#xff0c;亲…...

2023年4月北京/西安/郑州/深圳CDGA/CDGP数据治理认证考试报名

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…...

Win10桌面我的电脑怎么调出来?最简单方法教学

Win10桌面我的电脑怎么调出来&#xff1f;有用户发现自己的电脑桌面没有我的电脑这个程序图标&#xff0c;每次要访问磁盘的时候&#xff0c;开启都非常的麻烦。那么怎么将这个图标设置到桌面显示呢&#xff1f;接下来我们一起来看看以下的解决方法吧。 方法一&#xff1a; 在开…...

开启单细胞及空间组学行业发展黄金时代!首届国际单细胞及空间组学大会在穗闭幕

2023年4月16日&#xff0c;首届TICSSO国际单细胞及空间组学大会圆满闭幕&#xff0c;本次大会吸引了2000余位来自产、学、研、资、医、政、媒等业界人士齐聚羊城&#xff0c;注册总人数5398人&#xff0c;网络播放总量达548245人次&#xff0c;网络观看覆盖美国、德国、日本、澳…...

YOLOv8 更换主干网络之 GhostNetV2

《GhostNetV2:Enhance Cheap Operation with Long-Range Attention》 轻量级卷积神经网络(CNN)是专门为在移动设备上具有更快推理速度的应用而设计的。卷积操作只能捕捉窗口区域内的局部信息,这防止了性能的进一步提高。将自注意力引入卷积可以很好地捕捉全局信息,但这将大…...

高级服务框架(黑马)

一、修改order-service服务 修改OrderService&#xff0c;让其监听Nacos中的sentinel规则配置。 具体步骤如下&#xff1a; 1.引入依赖 在order-service中引入sentinel监听nacos的依赖&#xff1a; <dependency><groupId>com.alibaba.csp</groupId><…...

Go语言面试题--基础语法(29)

文章目录 1.下面的代码有什么问题&#xff1f;2.下面代码最后一行输出什么&#xff1f;请说明原因3.下面代码有什么问题&#xff1f;4.下面的代码输出什么&#xff1f; 1.下面的代码有什么问题&#xff1f; func main() {data : []int{1,2,3}i : 0ifmt.Println(data[i]) }参考…...

毕业生招聘信息的发布与管理系统(论文+设计)

前 言 当今&#xff0c;人类社会已经进入信息全球化和全球信息化、网络化的高速发展阶段。丰富的网络信息已经成为人们工作、生活、学习中不可缺少的一部分。人们正在逐步适应和习惯于网上贸易、网上购物、网上支付、网上服务和网上娱乐等活动&#xff0c;人类的许多社会活动…...

mysql安全加固配置文档(完结)

4. MySQL 权限安全配置 4.1. 确保只有管理员账号有所有数据库的访问权限 建议理由 除了管理员账号&#xff0c;其他用户没必要有所有数据库的访问权限。过高的权限会导致安全问题。检查方法 SELECT user, host FROM MySQL.user WHERE (Select_priv Y) OR (Insert_priv Y) …...

CAPL函数在实现AES加密算法时遇到的各种问题(c++中符号的含义,AES算法中padding的问题等)

本来打算把AES算法的代码移植到CAPL中的,文章:https://blog.csdn.net/qq_28205153/article/details/55798628?spm=1001.2014.3001.5506里有非常详细的代码。但是一来太麻烦,二来没必要,因为CAPL提供了Security安全相关的函数: 这里面就提供了AES加密算法的接口函数,使用…...

二叉排序树(二叉查找树)基本操作_20230417

二叉排序树&#xff08;二叉查找树&#xff09;基本操作_20230417 前言 二叉排序树首先是一颗二叉树&#xff0c;它不同于常规二叉树的地方在于&#xff0c;如果左子树不为空&#xff0c;那么左子树上所有结点的值都不大于根节点的值&#xff0c;如果右子树不为空&#xff0c…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案

引言 在分布式系统的事务处理中&#xff0c;如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议&#xff08;2PC&#xff09;通过准备阶段与提交阶段的协调机制&#xff0c;以同步决策模式确保事务原子性。其改进版本三阶段提交协议&#xff08;3PC&#xf…...