测试框架 Junit
# 02. 测试框架 Junit
介绍下 Junit
# 为什么要测试框架
我们想要测试某个方法的话,怎么做呢?如果用传统的测试,很不方便。
首先,一个类只能有一个 main 方法,如果要测试多个,需要注释之前的测试代码 或者 新建多个测试类。测试代码分散,不利于维护。
因此,专门用来测试的框架出现了;基本上目前最流行的就是 Junit 了,可以说是事实上的测试框架了
# Junit 介绍
JUnit 是一个 Java 语言的单元测试框架。它由 Kent Beck 和 Erich Gamma 建立,逐渐成为源于 Kent Beck 的 sUnit 的 xUnit 家族中最为成功的一个。 JUnit 有它自己的 JUnit 扩展生态圈。多数 Java 的开发环境都已经集成了 JUnit 作为单元测试的工具。
目前用的比较多的是 Junit4,为了简单,本文也是使用 Junit4 演示。
# 下载依赖
一般来说 IDE 都支持直接执行(因为 IDE 自己内置了 Junit 框架的依赖),我们只需写上@Test 的注解,然后将鼠标放上去,就会提示“将 Junit4 添加到类路径中”,这样就不用自己下载 jar 包了。
如果想手动下载依赖,可以去一个中央仓库的地方下载仪依赖:Maven Repository: junit » junit (opens new window)
也可以从我的 GitHub 仓库里下载 jar 包(junit-4.13.2.jar):
Gitee:lib · /LearnJavaEE - Gitee (opens new window)
GitHub:LearnJavaEE/lib at master · Peter-JXL/LearnJavaEE (opens new window)
如果你会 Maven:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
2
3
4
5
6
7
# 定义一个被测试的类
既然是要用测试框架,首先得有一个被测试的类,这里简单定义一个计算器类
package chapter5Junit;
public class Calculator {
public int add (int a, int b){
return a + b;
}
}
2
3
4
5
6
7
# 定义一个测试类
测试类的命名建议:
- 测试类名:被测试的类名 + Test 例如:
CalculatorTest
- 包名:被测试的类所在的包 + 例如:
com.peterjxl.test
新建一个 CalculatorTest 类,然后引入 Junit 的 Test 注解
package chapter5Junit.test;
import chapter5Junit.Calculator;
import org.junit.Test;
public class CalculatorTest {
}
2
3
4
5
6
7
8
定义测试方法,建议:
- 方法名:test 测试的方法名,例如
testAdd()
- 方法前面:必须是 public void
- 参数列表:空参,不能带参数
然后给方法加@Test 注解,然后执行测试方法
@Test
public void testAdd(){
}
2
3
4
完整代码:
package chapter5Junit.test;
import chapter5Junit.Calculator;
import org.junit.Test;
public class CalculatorTest {
@Test
public void testAdd(){
System.out.println("Hello Junit!");
Calculator c = new Calculator();
int result = c.add(1,2);
System.out.println(result);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 执行测试方法
注意,为了方便我们在 IDE 里执行。虽然用命令行也可以,但是会麻烦一点,这里就不演示了。
每个@Test 注解的方法,左侧就会有一个可执行的箭头:点击即可运行
运行结果:
如果测试失败,控制台会输出报错信息。
我们可以定义多个测试方法,每个测试方法上都加一个@Test 注解,可以逐个运行测试方法,也可以一次性运行所有@Test 的方法。
有时候,我们希望测试一下异常的情况,或者对方法运行时间有要求,例如超过 100 毫秒就认为测试失败,可以在注解里加上几个参数:
@Test(expected = RuntimeException.class, timeout = 100)
public void testTest(){
throw new RuntimeException() ;
}
2
3
4
expected=XXException.class
:如果程序的异常和 XXException.class 一样,则测试通过
timeout=100
:如果程序的执行能在 100 毫秒之内完成,则测试通过
# 其他注解
Junit 还有很多方便的注解:@BeforeClass,@Before,@Test,@After,@AfterClass,我们一一介绍
@Test: 测试方法
@BeforeClass:所有测试开始之前运行。方法必须必须要是静态方法(static 声明)
@Before:每一个测试方法之前都会运行的方法。我们的测试方法,一开始总是要初始化一些数据的,例如创建一个对象,获取数据库连接资源等等;这样,每个测试方法都要初始化,有很多重复的代码。
为此,我们可以新建一个方法,里面专门初始化这些数据,并用@Before 注解;
这样,就避免了要在每个@Test 方法里初始化,减少重复代码
@After:每一个测试方法之后都会运行的方法。例如数据库资源的释放。即使测试方法异常了,该方法也会执行。
@AfterClass:方法必须要是静态方法(static 声明),所有测试结束之后运行
注意区分@BeforeClass 和@Before 的区别
- @Before 是每个测试方法运行之前都会运行,
- @BeforeClass 是会在所有测试方法运行之前执行,只会执行一次。
# Assert
一般我们会使用断言操作来处理结果,判断测试到底是否通过了,而不是通过控制台输出,因为观察输出是很难知道到底是否正常运行了,例如刚刚输出 3,谁知道正确结果到底是不是 3 呢?如果是其他人来测试,还得每个测试方法都看看输出结果是否正确,很麻烦。
语法:Assert.assertEquals(期望的结果,运算的结果);
assertEquals 有很多重载的方法,这里简单说一个
@Test
public void testAdd(){
Calcuator c = new Calcuator();
int result = c.add(1,2);
Assert.assertEquals(3, result);
}
2
3
4
5
6
# Junit5
Junit 的最新版本 JUnit5 于 2017 年发布。更早之前的 Junit 我们暂时不介绍了。
可以在官网下载 JUnit (opens new window),新版本的 Junit 分了几个模块
我们分别下载 junit-platform-launcher.jar, junit-jupiter-engine.jar,和 junit-vintage-engine.jar
不像之前的 Junit 版本所有的组件都包含在 Junit 这一个包中,新的 Junit5 准确的说包含三个包:
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
- JUnit platform ,从名字也可以看出来,Junit 已不仅仅想简单作为一个测试框架,更多是希望能作为一个测试平台,也就是说通过 JUnit platform,其他的自动化测试引擎或自己定制的引擎都可以接入这个平台实现对接和执行。
- JUnit Jupiter, 则是 Junit5 的核心,它包含了很多丰富的新特性来使 JUnit 自动化测试更加方便、功能更加丰富和强大。
- JUnit Vintage 则是一个对 JUnit3,JUnit4 兼容的测试引擎,使旧版本 junit 的自动化测试脚本可以顺畅运行在 junit5 下,其实也可以看作是基于 junit platform 实现的接入范例。
如果你使用 Maven,Junit 的坐标如下:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>5.13</version>
</dependency>
2
3
4
5
6
7