【JUnit】Java 单元测试框架 | 学习笔记

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 是否值为 100

    assertNotEquals(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/


文章内容来自个人学习总结
欢迎指出本笔记中存在的问题
未经本人同意禁止转载,不得用于商业用途
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值