目录
概述
Junit 是一个常用的Java单元测试框架,所谓的单元测试是对某一个单一实体的测试(比如某个具体的类或者类里的方法),Junit提供了注释来识别测试方法,提供了断言来测试预期结果,提供了测试运行来运行测试。
环境搭建
用Intellij IDEA建立一个maven quickstart项目,方法参考
https://blog.csdn.net/man_zuo/article/details/81316988
然后在pom.xml声明依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.3.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.3.2</version>
<scope>test</scope>
</dependency>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
目录说明
在maven项目里,项目代码和测试代码不是放在同一个地方的,而是用两个目录结构相同的文件夹来分别存放项目代码和测试代码。
比如下图中的main文件夹是用来存放项目代码,而test文件夹(用红框标注的)是用来存放测试代码的。
我这里的包路径com.test里含有test可能会引起一些歧义。。并不是说明在这个包下的就是测试文件,因为包名是可以随意改的(只是我懒得改了)。
基本用法
在main
文件夹下的 com.test包 新建一个包 JunitTest,在这个包中新建一个 Hello类。
package com.test.JunitTest;
/**
* Created by IntelliJ IDEA
*
* @author manzuo
* @date 2019/7/4 17:21
*/
public class Hello{
private String message = "Hello";
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
现在就用Junit来测试一下这个Hello类。
将输入光标移动到类名所在的位置,然后按下快捷键 alt + Enter
,选择Creat Test
选择Creat Test之后会弹出一个窗口,你可以设置要生成的测试类的一些属性,比如类名,包名等,在Member框里可以选择你要测试的方法,这里选择了getMessage()方法,当然也可以一次性选择多个方法,然后点击OK确定。
然后IDEA会自动帮你在test中相同的位置 生成一个测试类。@Test
表明这是一个测试用例。
在getMessage方法里编写测试。
asserEquals只是其中一个测试方法,还有很多其他测试方法,摘抄如下:
(一些参数的说明:expected 是指期望值,也就是你预期希望得到的值,actual 是指程序运行实质得到的值,condition 是指一个条件表达式,比如 'x>5 '
)
序号 | 方法和描述 |
---|---|
1 | void assertEquals(boolean expected, boolean actual) 检查两个变量或者等式是否平衡 |
2 | void assertTrue(boolean expected, boolean actual) 检查条件为真 |
3 | void assertFalse(boolean condition) 检查条件为假 |
4 | void assertNotNull(Object object) 检查对象不为空 |
5 | void assertNull(Object object) 检查对象为空 |
6 | void assertSame(Object expected,Object actual) assertSame() 方法检查两个相关对象是否指向同一个对象 |
7 | void assertNotSame(Object expected,Object actual) assertNotSame() 方法检查两个相关对象是否不指向同一个对象 |
8 | void assertArrayEquals(expectedArray, resultArray) assertArrayEquals() 方法检查两个数组是否相等(需要两个数组里对应的位置的元素都相等) |
时间测试 timeout
有时候,处于性能的考虑,我们对方法的执行所需的时间是有要求的,所以必须在规定的时间里执行完方法。Junit框架也提供了一个选项,可以规定测试用例运行的最大时间,如果测试用例运行时间超过了规定的最大时间,就会标注为失败
先修改一下Hello类的getMessage()方法
public String getMessage() throws Exception {
sleep(2000);//睡眠2秒后执行,该方法需要 import static java.lang.Thread.sleep;
return message;
}
- 1
- 2
- 3
- 4
然后修改一下测试类HelloTest的getMessage()方法
@Test(timeout = 1000)//规定该测试用例必须在1秒内运行完毕
public void getMessage() throws Exception {
Hello hello = new Hello();
assertEquals("Hello",hello.getMessage());
}
- 1
- 2
- 3
- 4
- 5
注解的使用
序号 | 注解和描述 |
---|---|
1 | @Test 这个注解说明依附在 JUnit 的 public void 方法可以作为一个测试案例。 |
2 | @Before 有些测试在运行前需要创造几个相似的对象。在 public void 方法加该注解可以使该方法需要在 test 方法前运行。 |
3 | @After 如果你将外部资源在 Before 方法中分配,那么你需要在测试运行后释放他们。在 public void 方法加该注解可以使得该方法需要在 test 方法后运行。 |
4 | @BeforeClass 在 public void 方法加该注解可以使得该方法需要在类中所有方法前运行。 |
5 | @AfterClass 它将会使方法在所有测试结束后执行。这个可以用来进行清理活动。 |
6 | @Ignore 这个注解是用来忽略有关不需要执行的测试的。 |
稍微修改一下刚刚的HelloTest 方法,来测试这些注解的使用
package com.test.JunitTest;
import org.junit.*;
import static org.junit.Assert.*;
public class HelloTest {
@BeforeClass
public static void beforClass(){
System.out.println("beforClass running");
}
@AfterClass
public static void afterClass(){
System.out.println("afterClass running");
}
@Before
public void before(){
System.out.println("before running");
}
@After
public void after(){
System.out.println("after running");
}
@Test
public void test1(){
System.out.println("test1 running");
}
@Test
public void test2(){
System.out.println("test2 running");
}
@Ignore
@Test
public void test3(){
System.out.println("test3 running");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
运行结果如下
所以可以得出如下结论:
@BeforeClass
注解的方法首先执行,并且只执行一次。@AfterClass
注解的 方法最后执行,并且只执行一次。@Before()
注解的方法针对每一个测试用例执行,但是是在执行测试用例之前。@After()
方法针对每一个测试用例执行,但是是在执行测试用例之后。@Test
注解每个测试用例@Ignore
标注的测试用例会被忽略
参数化测试
有时候,我们需要用不同的值去测试同一个方法。Junit4就提供了参数化测试机制,允许我们用不同的值去测试某一个测试用例。
为了使用参数化测试这个用了,我们先写一个算法,比如判断某个数是不是素数(除了1和它本身以外不再有其他因数)
package com.test.JunitTest;
/**
* Created by IntelliJ IDEA
*
* @author manzuo
* @date 2019/7/9 19:27
*/
public class PrimeNumberChecker {
public boolean isPrimeNumber(int number){
for (int i = 2; i < (number / 2); i++) {
if (number % i == 0) {
return false;
}
}
return true;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
现在就用不同的值来测试 isPrimeNumber()方法。首先,先用前面的方法,快速生成测试用例
然后通过下面的五个步骤,来修改PrimeNumberCheckerTes测试类,创建参数化测试
- 用 @RunWith(Parameterized.class) 来注释 test 类。
- 创建一个由 @Parameters 注释的公共的静态方法,它返回一个数组来作为测试数据集合。
- 创建一个公共的构造函数,它接受和一行测试数据相等同的东西。
- 为每一列测试数据创建一个实例变量。
- 用实例变量作为测试数据的来源来创建你的测试用例
package com.test.JunitTest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.*;
@RunWith(Parameterized.class) // 用 @RunWith(Parameterized.class) 来注释 test 类
public class PrimeNumberCheckerTest {
private int number;//测试数据里的数字
private boolean expectedResult;//测试数据里期望的结果
private PrimeNumberChecker primeNumberChecker;//一个实例
/* 创建一个由 @Parameters 注释的公共的静态方法,它返回一个数组来作为测试数据集合*/
@Parameterized.Parameters
public static Collection primeNumbers(){
Object [][] objects = { //测试数据集合
{ 2, true },// 2是素数
{ 3, true },// 3是素数
{ 9, false },//9不是素数
{ 19, true},
{ 22, false },
{ 23, true }};
return Arrays.asList(objects);
}
/*创建一个公共的构造函数,它接受和一行测试数据相等同的东西。*/
public PrimeNumberCheckerTest(int number, boolean expectedResult) {
this.number = number;
this.expectedResult = expectedResult;
}
/*为每一列测试数据创建一个实例变量*/
@Before
public void initialize() {
primeNumberChecker = new PrimeNumberChecker();
}
/*用实例变量作为测试数据的来源来创建你的测试用例*/
@Test
public void isPrimeNumber() {
System.out.println("number = "+ number);
assertEquals(expectedResult,primeNumberChecker.isPrimeNumber(number));
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
运行测试结果如下: