【测试开发篇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 的缩写,就是“表现层资源表述状态转移” 1.1、Resource(资源) web应用的文件,uri定位 1.2、Representation(资源的描…...

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

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

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

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

MyBatis详解(2)
8、自定义映射resultMap 8.1、resultMap处理字段和属性的映射关系 若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射 <!--resultMap:设置自定义映射属性:id:表示自定义映射的唯一标识type:查询…...

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关键字(C11)1.1. 类型别名的思考1.2. auto简介1.3. auto使用情景1.4. auto的使用细则1.5. auto不能推导的场景 1.auto关键字(C11) 1.1. 类型别名的思考 随着程序越来越复杂,程序中用到的类型也越来越复杂…...

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

2023年4月北京/西安/郑州/深圳CDGA/CDGP数据治理认证考试报名
DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业发展里程碑及发展阶梯定义,帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力,促进开展工作实践应用及实际问题解决,形成企业所需的新数字经济下的核心职业…...

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

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

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

高级服务框架(黑马)
一、修改order-service服务 修改OrderService,让其监听Nacos中的sentinel规则配置。 具体步骤如下: 1.引入依赖 在order-service中引入sentinel监听nacos的依赖: <dependency><groupId>com.alibaba.csp</groupId><…...

Go语言面试题--基础语法(29)
文章目录 1.下面的代码有什么问题?2.下面代码最后一行输出什么?请说明原因3.下面代码有什么问题?4.下面的代码输出什么? 1.下面的代码有什么问题? func main() {data : []int{1,2,3}i : 0ifmt.Println(data[i]) }参考…...

毕业生招聘信息的发布与管理系统(论文+设计)
前 言 当今,人类社会已经进入信息全球化和全球信息化、网络化的高速发展阶段。丰富的网络信息已经成为人们工作、生活、学习中不可缺少的一部分。人们正在逐步适应和习惯于网上贸易、网上购物、网上支付、网上服务和网上娱乐等活动,人类的许多社会活动…...

mysql安全加固配置文档(完结)
4. MySQL 权限安全配置 4.1. 确保只有管理员账号有所有数据库的访问权限 建议理由 除了管理员账号,其他用户没必要有所有数据库的访问权限。过高的权限会导致安全问题。检查方法 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
二叉排序树(二叉查找树)基本操作_20230417 前言 二叉排序树首先是一颗二叉树,它不同于常规二叉树的地方在于,如果左子树不为空,那么左子树上所有结点的值都不大于根节点的值,如果右子树不为空,…...

实现服务器版本的表白墙
目录 初始前端代码 网页初始效果 一、确定接口 二、编写代码 2.1 创建项目七步走 1、创建Maven项目 2、引入依赖 3、构建目录 4、编写代码 5、打包、部署 编辑 7、验证代码 三、具体的代码逻辑 3.1 服务器——两个服务接口 3.2 前端页面的代码 3.2.1 前端存档…...

TensorFlow 2 和 Keras 高级深度学习:6~10
原文:Advanced Deep Learning with TensorFlow 2 and Keras 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自【ApacheCN 深度学习 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。 不要担心自己的形象&#x…...

unity,制作一个环状滑动条
介绍 unity,制作一个环状滑动条 方法 1.导入png图片素材2.新建一个滑动条,两者图片都设置为图片3.调节slider的参数4.调节backgroud的参数5.fill area、fill的参数同上。 得到两个叠加的圆环。6.设置fill的背景颜色为红色7.设置fill填充方式࿰…...

2023-04-17 算法面试中常见的树和递归问题
二叉树和递归 0 LeetCode297 二叉树的序列化和反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据…...

3分钟通过日志定位bug,这个技能测试人必须会
♥ 前 言 软件开发中通过日志记录程序的运行情况是一个开发的好习惯,对于错误排查和系统运维都有很大帮助。 Python 标准库自带了强大的 logging 日志模块,在各种 python 模块中得到广泛应用。 一、简单使用 1. 入门小案例 import logging logging.ba…...

【论文总结】V-Shuttle:可扩展和语义感知的 Hypervisor 虚拟设备模糊测试
介绍 这是来自2021 CCS的一篇论文,作者有GaoningPan, Xingwei Lin, Xuhong Zhang, Yongkang Jia, Shouling Ji, Chunming Wu, Xinlei Ying, Jiashui Wang, Yanjun Wu。该论文提出V-shuttle的新框架来执行管控程序的模糊测试,该框架执行可扩展和语义感知…...

一篇文章让你搞懂TypeScript中的typeof()、keyof()是什么意思
TypeScript中的typeof()、keyof()是什么意思? 知识回调(不懂就看这儿!)场景复现核心干货👇👇👇举例引入字面量类型(literal types&…...

【机会约束、鲁棒优化】机会约束和鲁棒优化研究优化【ccDCOPF】研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

4月想跳槽的同学,没有更好的选择,可以去美团
在美团干了半年,说一下自己的感受,美团是一家福利中等,工资待遇中上,高层管理团队强大,加班强度一般,技术不错,办公环境一般,工作氛围中上,部门差距之间工作体验差距巨大…...

从输入url到页面展现(一)从浏览器解析url开始
前端面试有一道很考验人的问题,那就是:请你说一下从用户从输入url到页面展现的过程是怎样的?在接下来的一段时间呢,狗哥会从这一问题出发,开始剖析这个过程,希望可以让更多的小伙伴掌握到这个过程ÿ…...