最近在开发项目的时候需要写单元测试,之前一直没有接触过,于是从零开始入门学习,查了网上相关资料,总结成为笔记,在此感谢各位大佬的详细资料!!!
目录
0、背景
1、单元测试简介
2、实践
(1)创建项目
(2)创建Junit_Test_Demo的单元测试
(3)运行单元测试
补充:
1、关于Junit_Test_DemoTest需要注意:
2、几个常用的注解
3、@Test的一些属性
4、代码覆盖率
我们在写好一个函数或者类以后,需要检验我们的程序是否存在bug或者是否满足我们的需求,通常的做法就是将写好的函数在mian方法中调用,输入一些测试用例进行检验。当要检验的方法数量较少时,这种方法可行,但是当我们有大量的函数需要验证时,该方法就显得笨重且繁琐,往往需要我们人工检查输出的结果是否正确等,比较混乱。因此,单元测试就是用来解决这种繁琐问题的。
单元测试是对一个函数、一个类、一个模块甚至是一个系统进行正确性检验对过程。
我创建的项目名称为junit_test_demo,并创建了一个名为Junit_Test_Demo的类,添加如下代码:
public class Junit_Test_Demo {
// 加法
public int add(int a, int b) {
return a + b;
}
// 减法
public int subtract(int a, int b) {
return a - b;
}
// 乘法
public int multiply(int a, int b) {
return a * b;
}
// 除法
public double divide(int a, int b) throws Exception {
if (b == 0) {
throw new Exception("除数不能为零!");
}
else {
return a / b;
}
}
}
A. 配置junit4的Maven依赖
在pom.xml文件中添加如下内容,并设置自动导入项目依赖:
junit
junit
4.12
test
B. 将光标置于要添加单元测试的类名上,使用Cmd+shift+T快捷键,选择Create New Test...
C. 在弹出的对话框中勾选要添加单元测试的函数,点击OK
D. 此时会在项目的test目录下创建相应的单元测试类(一般命名规则:类名+Test),如Junit_Test_DemoTest,然后在相应的函数中添加测试代码如下:
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class Junit_Test_DemoTest {
@Before
public void setUp() throws Exception {
System.out.println("单元测试开始前相关操作...");
}
@After
public void tearDown() throws Exception {
System.out.println("单元测试结束后相关操作...");
}
@Test
public void add() {
/**
* assertEquals函数
* first param: Expected value 期望返回值
* second param: Actual value 实际返回值
*/
assertEquals(8, new Junit_Test_Demo().add(2,6));
}
@Test
public void subtract() {
assertEquals(7, new Junit_Test_Demo().subtract(9,2));
}
@Test
public void multiply() {
assertEquals(36, new Junit_Test_Demo().multiply(6,6));
}
@Test
public void divide() throws Exception {
/**
* assertEquals函数
* first param: Expected value 期望返回值
* second param: Actual value 实际返回值
* third param: delta value 误差范围,因为double或float类型值无法直接进行比较,满足一定误差范围即认为两者相等
*/
assertEquals(2, new Junit_Test_Demo().divide(8,4),0.001);
}
}
A. 点击Run Junit_Test_DemoTest,如果没有错误,全部测试通过,运行结果如下:
B. 下面我们修改一下multiply的测试数值,将第一个6改成4,目的让测试不通过,看会是什么结果:提示1个测试失败,3个通过,并给出了失败的详细原因。
未完待续。。。
(1)所有测试方法返回类型必须是void且无参数;
(2)一个方法之所以为测试方法,是由@Test来注解的;
(3)assertEquals方法作用是比较两个参数是否相等,测试的时候应该多选几个测试数值,比如临界值等;
(4)assertEquals方法不止可以比较两个int型参数,还可以比较其它类型参数,有多种重载形式;
(1)@Test:将一个方法标记为测试方法;
(2)@Before:每一个测试方法调用前必执行的方法;
(3)@After:每一个测试方法调用后必执行的方法;
(4)@BeforeClass:所有测试方法调用前执行一次,在测试类没有实例化之前就已被加载,需用static修饰;
(5)@AfterClass:所有测试方法调用后执行一次,在测试类没有实例化之前就已被加载,需用static修饰;
(6)@Ignore:暂不执行该方法;
现在我们来测试一下每个注解,修改单元测试类Junit_Test_DemoTest,修改内容如下:
增加一个构造函数Junit_Test_DemoTest;
增加函数setUpBeforeClass,并用@BeforeClass注解;
增加函数setUpAfterClass,并用@AfterClass注解;
将测试函数multiply用@Ignore注解;
import org.junit.*;
import static org.junit.Assert.*;
public class Junit_Test_DemoTest {
public Junit_Test_DemoTest() {
System.out.println("构造函数...");
}
@BeforeClass
public static void setUpBeforeClass() {
System.out.println("BeforeClass...");
}
@AfterClass
public static void setUpAfterClass() {
System.out.println("AfterClass...");
}
@Before
public void setUp() throws Exception {
System.out.println("单元测试开始前相关操作...");
}
@After
public void tearDown() throws Exception {
System.out.println("单元测试结束后相关操作...");
}
@Test
public void add() {
/**
* assertEquals函数
* first param: Expected value 期望返回值
* second param: Actual value 实际返回值
*/
assertEquals(8, new Junit_Test_Demo().add(2,6));
}
@Test
public void subtract() {
assertEquals(7, new Junit_Test_Demo().subtract(9,2));
}
@Ignore
public void multiply() {
assertEquals(36, new Junit_Test_Demo().multiply(6,6));
}
@Test
public void divide() throws Exception {
/**
* assertEquals函数
* first param: Expected value 期望返回值
* second param: Actual value 实际返回值
* third param: delta value 误差范围,因为double或float类型值无法直接进行比较,满足一定误差范围即认为两者相等
*/
assertEquals(2, new Junit_Test_Demo().divide(8,4),0.001);
}
}
运行结果如下:
从结果中得知:
@BeforClass和@AfterClass在构造方法前被调用了,且只调用了一次,一般用来初始化和关闭资源;
@Before和@After在每个@Test执行前后被调用
@Ignore被忽略;
构造函数执行了三次、三次、三次,这是为什么?这是因为Junit4为了保证每个测试方法都是单元测试,互不影响,在每个测试方法被调用前都会初始化出一个新的实例对象来执行。
excepted属性是用来测试异常的,即如果被测试的方法没有抛出异常,测试不通过,抛出异常,则测试通过。
我们在单元测试类中添加异常测试方法:
@Test (expected = Exception.class)
public void testDivideException() throws Exception {
new Junit_Test_Demo().divide(3,0);
fail("除数为零没有抛出异常");
}
该测试方法是(expected = Exception.class)和fail(“除数为零没有抛出异常”),会检查是否抛出Exception异常(也可以检查其他异常)。如果抛出异常测试通过,没有抛出异常测试不通过执行fail(“除数为零没有抛出异常”)。
该方法是用来测试性能的,测试一个方法能不能在规定时间内完成。用法和expected一样。
@Test (timeout = 1000)
public void testDivideTimeout() throws Exception {
new Junit_Test_Demo().divide(6,3);
}
收集覆盖率,通过Run→Run ‘Junit_Test_DemoTest’ with Coverage,运行结束后,IDEA将会在Projec工具窗口显示每个程序包、类的覆盖率数据,同时在Coverage工具窗和编辑器中也会显示。
参考资料:
[1]: https://blog.csdn.net/u011138533/article/details/52165577
[2]: https://blog.csdn.net/chenbetter1996/article/details/80441178