测试方法之Java白盒测试(二)
说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!
接着上一篇博客继续往下写 :https://blog.****.net/qq_41782425/article/details/103615186
文章目录
- 五、使用 JUnit 进行单元测试
- 4.JUnit 的安装和使用流程
- 4.1 第 1 步,安装 eclipse 及 jre
- 4.2 第 2 步,新建 Java 项目
- 4.3 第 3 步,将 JUnit 引入项目
- 4.4 第 4 步,编写被测类的代码
- 4.5 第 5 步,创建 JUnit 测试用例类
- 4.6 第 6 步,运行测试代码
- 5.JUnit 单元测试案例
- 5.1 在测试类中创建一个被测类对象
- 5.2 使用@Test 进行测试
- 5.3 使用@Before 进行测试前准备
- 5.4 使用@Ignore 忽略测试
- 5.5 使用@Test(timeout=?)进行超时限制测试
- 5.6 使用@RunWith 和@Parameters 进行参数化测试
- 5.6.1 什么是参数化
- 5.6.2 创建用@RunWith(Parameterized.class)注解的测试类
- 5.6.3 在新测试类中添加存储参数的成员变量
- 5.6.4 使用@Parameters 修饰测试数据集方法
- 5.6.5 编写类的构造函数
- 5.6.6 编写测试方法
- 5.6.7 读取文件中的数据进行参数化
- 5.7 使用@RunWith 和@Suite.SuiteClasses 运行测试集
- 6.使用 JUnit 的注意事项
五、使用 JUnit 进行单元测试
4.JUnit 的安装和使用流程
4.1 第 1 步,安装 eclipse 及 jre
说明: JDK——开发java程序用的开发包,JDK里面有java的运行环境(JRE),包括client和server端的,需要配置环境变量
JRE——运行java程序的环境,JVM、JRE里面只有client运行环境,安装过程中,会自动添加PATH
- 将eclipse及jre拷贝到桌面(博主使用纯净版win7进行演示)
- 将eclipse解压即可(免安装),因为博主只有一个C盘,所以只能解压到C盘了
- 安装jre,傻瓜式安装
- 打开C:\Eclipse目录下的eclipse.exe程序,并将该程序发送快捷方式到桌面,在打开程序时,出现如下提示
- 因为博主win7 并没有E盘,所以需要修改到C盘即可,点击确定后,成功进入欢迎界面
- 取消总是勾,关闭欢迎界面,不然每次打开eclipse都会出现欢迎
- 关闭初始化窗口
4.2 第 2 步,新建 Java 项目
- 右击项目资源管理空白处,新建——其他——选中Java项目——点击下一步
- 命名项目名称,点击下一步
- 最后点击完成,不关联透视图,因为不是做开发项目
- 回到JavaTest项目,展开src目录,在src下创建一个包
4.3 第 3 步,将 JUnit 引入项目
- 右击项目 JavaTest—>选择“构建路径”—>点击“配置构建路径”
- 在弹出的窗口中点击“库”选项卡,点击“添加库”按钮,在弹出的窗口中选择“JUnit”
- 之后选择“JUnit”版本,点击完成即可
4.4 第 4 步,编写被测类的代码
说明:编写一个程序,然后再编写代码来测试
- 编写一个能够简单实现加减乘除、平方、开方的计算器类,然后对这些功能进行单元测试。编写完成后,类无需编译。首先右击test包,新建一个类
- 代码编写如下(顺便给eclipse更换配置了主题)
4.5 第 5 步,创建 JUnit 测试用例类
- 右击test包,新建类——Java——JUnit——JUnit测试套件
- 在弹出页面命名类名,正在测试的类输入test包下的Calcultator即可
- 选择要测试的方法
- 点击完成后,则创建CalcTest类,并在这个类中有很多对应测试方法存根的方法
4.6 第 6 步,运行测试代码
- 右击CalcTest类,选择运行方式为Junit测试,即对CalcTest中的方法进行测试
- 查看测试运行结果,显示全部失败,这是因为方法中全是fail尚未实现,也就是失败
5.JUnit 单元测试案例
5.1 在测试类中创建一个被测类对象
5.2 使用@Test 进行测试
说明:以测试 Calculator 类的 add 方法为例进行演示
- 在testAdd方法中调用Calculator类中的add方法,并通过assertEquals方法来判断预期值与实际值是否一致,来到达测试的效果
- 运行代码,查看测过,全部通过
- 设计一个错误的用例,运行后,JUnit框架则显示出故障以及原因
5.3 使用@Before 进行测试前准备
5.3.1 测试 divide 方法
说明:以测试 Calculator 类的 divide方法为例进行演示
- 在testDivide方法中添加测试用例,如下
- 运行代码,结果显示故障,原因是前面编写的testAdd方法中执行的用例导致result变量的结果为5了,所以(8+5)/2 因为是int类型所以结果为6而不是4
5.3.2 加入@Before 注解
- 使用Before注解则可以完美解决,在CalcTest类中定义一个reset重置方法,在方法中调用clear方法使result变量的值为0,在这个方法上使用Before注解后,则在每个测试方法执行之前默认会去调用reset方法,就不会出现以上的问题
- 运行CalcTest类,testAdd和testDivide两个测试方法全部通过
5.3.3 测试 substract 方法
- 在testSubstract方法中编写如下代码
- 运行测试,结果发现居然出现了实际结果为9,与测试中的预期结果2不一致
- 那么则需要回到Calculator类中,查看调用的substract方法有没有问题,结果发现这里result = result-1;这句代码不对,应该是result = result-n;才对,所以导致了实际结果为10 - 1 = 9,而不是10-8 = 2
5.4 使用@Ignore 忽略测试
- 对于被测代码或者方法还未编写的,可以在对应测试方法上加上@Ignore 注解
- 运行代码,显示如下方法被跳过,而在Python语言中和@unittest.skip方法一样都是跳过此测试方法
5.5 使用@Test(timeout=?)进行超时限制测试
- 测试 squareRoot 求平方根方法使用@Test(timeout=?)设定超时时间
- 运行代码,显示2秒后,进行断言测试,显示了一个错误
- 按理来说4的平方根为2没有问题啊,但是此时程序报错了,那么查看被测代码中的squareRoot方法,结果发现里面是死循环,所以出错了
5.6 使用@RunWith 和@Parameters 进行参数化测试
5.6.1 什么是参数化
-
怎么测试多分支?
√ 如一个对考试分数进行评价的函数
✰ 返回值分别为“优秀,良好,一般,及格,不及格”
✰ 在编写测试的时候,如果编写 5 个测试方法,进而测试 5 种情况,是一件很麻烦的事情。 -
为了简化类似的测试,JUnit 提出了“参数化测试”的概念,只写一个测试函数,把这若干种情况作为参数传递进去,一次性的完成测试。
5.6.2 创建用@RunWith(Parameterized.class)注解的测试类
-
若使用参数化测试,必须指定一个 Runner,这个 Runner 就是 Parameterized,其写法是@RunWith(Parameterized.class)。
√ 必须生成一个新的测试类,不能与其他测试共用同一个类;
√ 必 须 在 类 前 使 用 @RunWith(Parameterized.class) 指 定 运 行 器 为Parameterized; -
在类中创建一个 Calculator 的对象以便调用其被测试的方法。这里假设新建测试类命名为 SquareTest,代码如下:
@RunWith(Parameterized.class)//注意包含相应的包 -
另外创建一个测试类SquareTest
-
创建@RunWith(Parameterized.class)注解测试类,在类中创建一个Calculator的对象
5.6.3 在新测试类中添加存储参数的成员变量
- 在类中定义两个变量,一个用于存放参数,一个用于存放期待的结果
5.6.4 使用@Parameters 修饰测试数据集方法
- 定义获得测试数据集的方法,该方法必须使用@Parameters 标注进行修饰
5.6.5 编写类的构造函数
-
功能是对先前定义的两个参数进行初始化。
√ 注意参数的顺序要和上面的数据集合的顺序保持一致。
✰ 如果前面的顺序是{参数,期待的结果},那么构造函数的顺序也要是“构造函数(参数, 预期结果)”。 -
具体代码实现如下
5.6.6 编写测试方法
- 之前在CalcTest类中存在testSquare方法,可以将其进行注释掉,然后在SquareTest类中,来编写testSquare方法,最后在getParamResult方法需要添加@Parameters注释来调用此方法获取参数
- 执行代码,两个故障一个通过,跟我们设计的二维数组的到达的平方值一致
- 整个程序的执行流程为
5.6.7 读取文件中的数据进行参数化
-
打开文件
File file=new File(文件路径) -
读取文件
FileReader bytes=new FileReader(file)
BufferedReader chars=new BufferedReader(bytes); -
读取文件中的行
while((row=chars.readLine())!=null) -
拆分行中的列
row.split("\t") -
关闭文件
chars.close() -
首先创建一个java类,需要勾选main方法,因为在编写过程中要测试文件数据是否读取成功
-
然后在电脑桌面创建一个case.txt文件,用于读取文件数据使用,文件内容如下,适于求数的平方,需要注意的是最好用tab键进行分割
-
编写如下代码,读取case.txt文件中的第一行数据
-
运行代码,读取第一行数据成功正确
-
通过while循环来读取文件中所有的数据,条件为row 字符串的值不为空
-
拆分行中的列,并将数据存在数据中,遍历数据将每个值存放到num变量中并进行打印
-
将绝对路径修改为项目路径,方便以后迁移项目不将文件遗漏
-
修改SquareTest类中的getParamResult参数化方法
-
运行代码,方法没有问题
-
现在不需要从Object二维数组中获取数据,而是从文件中去获取,所以将ReadFile类中获取文件数据的代码直接粘贴到getParamResult方法中,需要统计文件中的行数以及将文件中的数据拆分到数组中(需要有java基础知识)
-
将代码复制到ReadFile类中进行测试,并循环换行打印出data二维数组中的每一列数据
-
运行代码,成功打印出每一行数据
-
回到SquareTest类中,运行代码,查看测试结果,显示参数类型不匹配全部出错了
-
那是因为Object类的data数组赋值给param及result这个两个int类型时不匹配报错了,将Object替换为Integer类型,最后将column[j] String类型的值转换为Integer即可
-
重新运行代码,全部通过
5.7 使用@RunWith 和@Suite.SuiteClasses 运行测试集
5.7.1 什么是测试集
-
也称打包测试、测试套件。
-
在一个项目中,只写一个测试类是不可能的,我们会写出很多很多个测试类。可是这些测试类必须一个一个的执行,比较麻烦。
-
JUnit 提供运行测试集的功能,将所有需要运行的测试类集中起来,一次性的运行完毕,大大的方便测试工作。
5.7.2 @RunWith(Suite.class)和@Suite.SuiteClasses 注解
-
打包测试也需要使用一个 Runner ,需要向 @RunWith 标注传递一个参数Suite.class。
-
同时,还需要另外一个标注@Suite.SuiteClasses,来表明这个类是一个打包测试类,在内部需要提供需要运行的测试类的名字。
-
新建一个java类,使用@RunWith注解并传递Suite.class参数
-
在AllTest类上添加@Suite.SuiteClasses注解,将很多类打包到一个套件中
-
运行代码,则会执行测试套件中传递的所有测试类中的测试方法
6.使用 JUnit 的注意事项
-
测试类和测试方法应该有一致的命名方案。
-
确保测试与时间无关,不要依赖使用过期的数据进行测试,导致在随后的维护过程中很难重现测试。
-
测试(测试量或代码规模)要尽可能地小,执行速度快。
-
不要硬性规定数据文件的路径。
-
利用 JUnit 的自动异常处理书写简洁的测试代码。
√ 事实上在 JUnit 中使用 try-catch 来捕获异常是没有必要的,JUnit 会自动捕获异常,那些没有被捕获的异常就被当成错误处理。