一. 为什么开发要写测试代码?
我认为有以下几点:
- 开发自己写的生产代码需要自己负责它是否正确,而不是依靠测试人员发现甚至是发布到生产让用户发现。
- 开发自己测试的反馈时间是最短的,可以大大节省团队交付时间。问题反馈周期排序:开发 < 测试 < 产品验收 < 用户。
- 把测试自动化,提升测试效率。
- 开发是最了解自己写的代码,对于自己测试来说是白盒的,对于其他人来说是黑盒的。
- 自己写了测试代码并验证通过,对代码有信心。
测试的好处远远不止这些,只有经常写测试体会才更加深刻,让我们开始实战吧!
二. 入门 Junit 5
首先我们用 Spring Initializr 项目新建一个Java项目。下载新建的项目后,用擅长的IDE打开,就可以开始 Coding 了(前提是需要依赖JAVA运行环境)。
假设我们有一个 Calculator 类,里面有一个 add 方法
public class Calculator {
public int add(int first, int second) {
return first + second;
}
}
我们开始编写第一个测试,验证 Calculator 类提供的 add 方法。
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class MyFirstTest {
@Test
void should_be_able_to_addition() {
Calculator calculator = new Calculator();
assertEquals(2, calculator.add(1, 1));
}
}
我们的第一个测试就完成了,当 1 加 1 等于 2,我们就认为测试通过,当然,如果遇到一些情况复杂的方法,并不是只验证一条测试用例通过就通过。
测试的本质就是根据输入得到输出,然后比较输出是否符合我们的预期。如果符合预期,说明功能正确,否则功能错误。
忽略某个测试执行用 @Disabled 注解
@Disabled
@Test
void should_be_able_to_addition() {
Calculator calculator = new Calculator();
assertEquals(2, calculator.add(1, 1));
}
验证 Bool 值 (assertTrue)
@Test
void should_be_able_to_true() {
assertTrue(1 < 2);
}
捕获异常测试 (assertThrows)
public class Calculator {
public int divide(int dividend, int divisor) {
return dividend / divisor;
}
}
@Test
void should_be_able_to_catch_exception() {
Calculator calculator = new Calculator();
Exception exception = assertThrows(ArithmeticException.class, () ->
calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());
}
统一的测试前置和收尾工作,可以在运行测试前开启和初始化资源,在测试结束后关闭和删除资源。
@BeforeEach
void setUp() {
// 运行在每一个 @Test 之前执行
}
@BeforeAll
static void beforeAll() {
// 运行在所有 @Test 之前执行
}
@AfterEach
void tearDown() {
// 运行在每一个 @Test 之后执行
}
@AfterAll
static void afterAll() {
// 运行在所有 @Test 之后执行
}
到此,对于初学者来说就写一些简单的测试了,但着对于真实项目中开发还是不够用的。
三.写在后面
对于有开发经验的伙伴来说,写测试还是挺简单的。毕竟一些复杂的业务场景也有实现,测试只是构造一些数据和场景来覆盖业务代码并且验证返回结果。
不过测试的路也还长着,这还只是基本的测试,后面会继续在项目中的测试怎么写,根据测试来驱动开发的实践。
路漫漫其修远兮,开发是一件挺有趣的事情,趁闲暇时光,沉淀,笃行。