Java 单元测试框架 | 学习笔记
文章目录
一. 单元测试
1. 何为单元测试
- 单元测试是针对最小功能单元编写测试代码
- Java 程序最小功能单元是方法
- 单元测试针对单个 Java 方法的测试
2. 单元测试的优点
- 确保单个方法运行正常
- 如果修改了方法代码只需要确保其对应的单元测试通过
- 测试代码本身可以作为示例代码
- 可以自动化运行所有的测试并或得报告
二. 测试驱动开发 TDD(Test-Driven Development)
测试驱动开发流程
三. JUnit 介绍
1. Junit 是一个开源的 Java 语言的单元测试框架
- 针对 Java 语言设计,使用最广泛
- JUnit 是事实上的标准单元测试框架
2. JUnit 的特点
- 使用断言(Assertion)测试期望结果
- 可以方便地组织和运行测试
- 可以方便的查看测试结果
- 常用的 IDE 都集成了 JUnit
- 可以方便的集成到 Maven 中
四. JUnit 中的概念
- TestCase:一个 TestCase 表示一个测试
- TestSuite:一个 TestSuite 包含一组 TestCase ,表示一组测试
- TestFixture:一个 TestFixture 表示一个测试环境
- TestResult:用于收集测试结果
- TestRunner:用于运行测试
- TestListener:用于监听测试过程,并收集数据
- Assert:用于断言测试结果是否正确
五. 断言测试
断言总览(未录的一些断言方法可以参见 JUnit API 的 Assert 类了解学习)
断言方法 | 测试效果 | 备注 |
---|---|---|
assertEquals(int a, int b) | 测试值 a 与b是否相等 | 该方法与多种数据类型重载,详细参见 JUnit API 的 Assert 类 |
assertNotEquals(int a, int b) | 测试值 a 与 b 是否不相等 | 同上 |
assertArrayEquals(int[] a, int[] b) | 测试数组 a 与数组 b 是否相等。两数组必须顺、大小、值完全相同才能通过测试 | 该方法与多种数据类型的数组重载,详细参见JUnit API 的Assert 类 |
assertNull(Object x) | 测试值 x 是否为空 | |
assertNotNull(Object x) | 测试 x 是否不为空 | |
assertTrue(boolean x) /assertFalse(boolean x) | 测试 x 是否为真/测试 x 为假 | 可以书写逻辑运算表达式 |
assertSame(Object a, Object b) | 测试 a 和 b 的引用是否指向同一个对象 |
简单使用
-
断言相等与不相等
assertEquals(100, x);
测试 x 是否值为 100assertNotEquals(100, x);
测试 x 是否值不为 100 -
断言数组相等
assertArrayEquals(y, x);
测试 x 是否与 y 数组相等
-
浮点数断言相等
assertEquals(3.1416, x, 0.0001);
测试 x 是否在精度为 0.0001 的情况下与 3.1416 相等 -
断言为null或不为 null
assertNull(x);
测试x是否为空
assertNotNull(x);
测试x不为空 -
布尔值断言
assertTrue(x>0);
assertFalse(x<0);
测试值为true / false
Assert测试案例
注意:JUnit以方法为测试单元,因此作为测试的方法需要加上 @Test 注解
package org.example.test
import org.junit.Test;
import static org.junit.Assert.*;
public class Test {
//测试方法需要加上@Test注解
@Test
public void test1() {
assertEquals(5,2+3);
}
@Test
pubic void test2() {
assertEquals(3.1415926,3.1415927,0.00000001);
}
}
//若测试通过,控制台上将不会显示任何信息
运行以上测试方法 test2 时,测试失败,控制台将会显示以下信息:
(运行环境为 Java8,IDEA 2020。只截取了部分关键运行结果信息如下)
java.lang.AssertionError:
Expected :3.1415926
Actual :3.1415927
<Click to see difference>
...
六. JUnit Fixture
-
@Before
与@After
每个
@Test
方法执行前都会执行@Before
方法。主要用于创建@Test
方法需要的一些资源。若有多个@Test
方法,每次执行@Test
方法前都会单独执行@Before
方法,使得资源互不影响。@After
同理,用于关闭一些资源,在@Test
方法完成后执行。package org.example.test import static org.junit.Assert.*; import static org.junit.Before; import static org.junit.After; public class Test { Main m; @Before public void setUp() { m = new Main(); } @After public void setDown() { System.out.println("A test method is finish"); } @Test public void testMain() { assertEquals(5,m.add(2,3)); } }
-
@BeforeClass
与@AfterClass
@BeforeClass
在所有测试方法执行前执行的方法,一般用于创建非常耗时的资源。@AfterClass
在所有测试方法执行之后执行的方法,一般用于清理资源。
总测试
package org.example.test
import static org.junit.Assert.*;
import static org.junit.*;
public class Test {
@BeforeClass
public void setUpBeforClass() {
System.out.println("BeforeClass method is running");
}
@AfterClass
public void setDownAfterClass() {
System.out.println("AfterClass method is running");
}
@Before
public void setUp() {
System.out.println(" Before method is runing");
}
@After
public void setDown() {
System.out.println(" After method is running");
}
@Test
public void TestA() {
System.out.println(" TestA method is running");
}
@Test
public void TestB() {
System.out.println(" TestB method is running");
}
@Test
public void TestC() {
System.out.println(" TestC method is running");
}
}
测试结果
BeforeClass method is running
Before method is runing
TestA method is running
After method is running
Before method is runing
TestB method is running
After method is running
Before method is runing
TestC method is running
After method is running
AfterClass method is running
运行结果,方法执行顺序,图解
七. 测试异常
在 @Test
注释中加入参数例如:
@Test(expected = NumberFormatException.class)
表示该测试方法预期发生 NumberFormatException,若发生该异常则测试成功
八. 参数化测试
如果待测试的输入是一组数据则可以使用参数化测试,这使得测试可以用一组数据来进行多项测试
- 可以把测试数据组织起来
- 用不同的则是数据调用相同的测试方法
package org.example.test
import static org.junit.Assert.*;
import static org.junit.*;
@RunWith(Parameterized.class)
public class Test {
private int input;
private int expected;
@Parameters
public static Collection data() {
//这里定义了一组测试数据
return Arrays.asList(new Object[][] {{0,0},{1,1},{-1,1}});
}
public Test(int input,int expected) {
this.input = input;
this.expected = expected;
}
@Test
public void testAbs() {
//此时使用测试类的全局变量
//将会使用 data 方法中的数据组进行逐对测试
assertEquals(this.expected,Math.abs(this.input));
}
}
进行参数化测试要求:
- 参数必须由静态方法 data() 返回
- 返回类型为 Collection<Object[]>
- 静态方法必须注释为
@Parameters
- 测试类必须注释为
@RunWith(Parameterized.class)
- 构造方法参数必须和测试参数对应
九. 超时测试
在 @Test 注释中加以参数以实现执行超时测试。例如:
@Test(timeout = 500)
该方法若超过 500ms 还未完成则测试结果为超时
JUnit 4.13 API文档: https://junit.org/junit4/javadoc/latest/