前言,发现了一个b站的宝藏UPYimcode,搬运一些外国的java视频,很适合初级程序员学习,本篇文章内容总结自你真的会写单元测试吗。
文章目录
- 单元测试
- 一、认识单元测试
- 二、Junit
- 1、导入依赖
- 2、使用一个简单的测试类
- 2.1 创建测试类
- 注意:
- 2.2、使用断言,编写测试内容
- 2.3、运行测试
- 三、完善单元测试
- 1、多条件测试才能保证符合预期
- 2、单元测试的覆盖率
- 3、根据边缘条件继续提高覆盖率
- 4、使用断言来处理异常
- 总结
一直听大厂的程序员在提到的东西,但是以我目前的水平比较难接触,不过作为程序员总是要向上看才对,,就通过这个视频来总结一些自己的收获吧。视频的思路总结如下:
unit testing unit testing is a type of software testing where one individual piece of code or unit ,is being tested by itself so a unit test isolates one single piece of code and verifies that piece is working correctly usually for java that single piece of code is going to be a class or even a method inside a class ,so unit tests are just code that you write also in java that individual method that you want to test and verify that it’s doing exactly what it should do
<dependencies>
<dependency>
<groupId>org.junit.jupitergroupId>
<artifactId>junit-jupiterartifactId>
<version>5.9.2version>
<scope>testscope>
dependency>
dependencies>
创建一个目标类如下:
package com.zhc.demo;
public class Calculator {
public int add(int a, int b) {
return a + b;
}
}
点击空白处 ,使用IDEA的快捷键 CTRL+SHIFT+T
创建测试类
测试类的报路径应该和目标类一致
测试类命名规则: 类名 为 目标类+Test
测试方法命名规则: 条件A ShouldReutrn 条件B
对应的测试方法上应该加入注解 @Test
IDEA自动生成的测试在符合上述规则的条件下,还导入了junit提供的断言Assert包。
完整初始测试类如下
package com.zhc.demo;
import static org.junit.jupiter.api.Assertions.*;
class CalculatorTest {
}
比如这次要使用的是比较断言,需要传入两个参数,前面的期望,后面是实际,比较结果不同就会抛出异常:
也可以使用 布尔断言,判断结果是否为true 或false来判断。写法如下:
assertEquals( 4 , calculator.add(2 , 2));// 比较断言
assertTrue(calculator.add(2 ,2) == 4); // 布尔断言
运行成功则没有提示,如何运行失败,则会报出异常
以目标类是加法计算为例,如果把目标类的加法,改成乘法,我们会发现 输入的参数(2 ,2)得出的结果也是4 ,这就涉及到测试的完善程度的问题了。
所以,一个完善的单元测试,一个方法要用多个条件进行测试才对。
视频中使用了一个多分支方法,来模拟该场景,我也写一个demo,如下
package com.zhc.demo;
public class Multiple {
public String multipleBranch(int num){
if (num < 0) {
throw new IllegalArgumentException("参数不合法:应该大于0");
}
else if (num < 60 ){
return "D";
}
else if (num < 70 ){
return "C";
}
else if (num < 80 ){
return "B";
}
else {
return "A";
}
}
}
测试方法如下
package com.zhc.demo;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class MultipleTest {
@Test
void fiftyNineShouldReturnD() {
Multiple multiple = new Multiple();
assertEquals("D" , multiple.multipleBranch(59));
}
@Test
void sixtyNineShouldReturnC() {
Multiple multiple = new Multiple();
assertEquals("C" , multiple.multipleBranch(79));
}
@Test
void seventyNineShouldReturnB() {
Multiple multiple = new Multiple();
assertEquals("B" , multiple.multipleBranch(89));
}
@Test
void ninetyNineShouldReturnA() {
Multiple multiple = new Multiple();
assertEquals("A" , multiple.multipleBranch(99));
}
}
运行测试后可以查看到覆盖率:
双击可以跳转到对应的类下:
根据前面的简单场景的单元测试,我们提供了一个高覆盖率的测试场景。但是思考一下,如果我修改原方法——比如“将D的条件改为 (num < 65)”,我们会发现测试依然的通过的。
所以这个时候就需要考虑到边缘条件的问题了。
在上述的案例中,就需要继续添加新的测试条件:对num 等于60/80/90的场景,再分别进行测试,以确保目标方法符合预期。
在正常的操作中,抛出异常就以为的测试失败。但是有些场景,比如上述的分级案例,就是要抛出异常才是符合预期的,应该如何测试呢?视频里给出的写法。
异常断言assertThrows
:第一个参数的异常类.class,第二个参数的一个lambda表示来表示运行的方法内容。
@Test
void negativeOneShouldReturnIllegalArgumentException(){
Multiple multiple = new Multiple();
assertThrows(IllegalArgumentException.class ,
() -> {
multiple.multipleBranch(-1);
});
}
在实际的开发中,一个完整的单元测试不仅要保障代码正常运行,还要保障测试代码覆盖了所有的分支,并且要根据边缘条件,尽可能的确保目标方法符合预期。
为了确保你的代码是正确的,我们可以编写一堆测试场景,这样做有以下好处
最后作者做了一个小重构,将案例中的else都删除了,而且符合预期,说明重构成功了。