JUnit简介

JUnit是由 Erich Gamma和Kent Beck编写的一个回归测试框架(regression testing framework)。JUnit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。

2.核心—断言

断言是编写测试用例的核心实现方式,即期望值是多少,测试的结果是多少,以此来判断测试是否通过。

1. 断言核心方法

assertArrayEquals(expecteds, actuals) 查看两个数组是否相等。
assertEquals(expected, actual) 查看两个对象是否相等。类似于字符串比较使用的equals()方法
assertNotEquals(first, second) 查看两个对象是否不相等。
assertNull(object) 查看对象是否为空。
assertNotNull(object) 查看对象是否不为空。
assertSame(expected, actual) 查看两个对象的引用是否相等。类似于使用“==”比较两个对象
assertNotSame(unexpected, actual) 查看两个对象的引用是否不相等。类似于使用“!=”比较两个对象
assertTrue(condition) 查看运行结果是否为true。
assertFalse(condition) 查看运行结果是否为false。
assertThat(actual, matcher) 查看实际值是否满足指定的条件
fail() 让测试失败

3.核心—注解

1. 说明

@Before 初始化方法
@After 释放资源
@Test 测试方法,在这里可以测试期望异常和超时时间
@Ignore 忽略的测试方法
@BeforeClass 针对所有测试,只执行一次,且必须为static void
@AfterClass 针对所有测试,只执行一次,且必须为static void
@RunWith 指定测试类使用某个运行器
@Parameters 指定测试类的测试数据集合
@Rule 允许灵活添加或重新定义测试类中的每个测试方法的行为
@FixMethodOrder 指定测试方法的执行顺序

2. 执行顺序

一个测试类单元测试的执行顺序为:

@BeforeClass –> @Before –> @Test –> @After –> @AfterClass

每一个测试方法的调用顺序为:

@Before –> @Test –> @After

JUnit常用注解介绍

@Test:JUnit 3.x是通过对测试方法的命名(test+方法名)来确定是否是测试,且所有的测试类必须继承TestCase。JUnit 4.x只需要在方法前加上@Test 就可以定义一个测试方法。

注意:测试方法必须是public void,即公共、无返回值的;可以抛出异常

@Ignore :该注解标记的测试方法在测试中会被忽略当测试的方法还没有实现,或者测试的方法已经过时,或者在某种条件下才能测试该方法(比如需要一个数据库连接,而在本地测试的时候,数据库并没有连接),那么使用该注解来标记这个方法。同时可以为该注解传递一个String的参数,表明为什么会忽略这个测试方法。比如:@lgnore(“该方法还没有实现”),在执行的时候,仅会报告该方法没有实现,而不会运行测试方法。

@BeforeClass:当我们运行几个有关联的用例时,可能会在数据准备或其它前期准备中执行一些相同的命令,这个时候为了让代码更清晰,更少冗余,可以将公用的部分提取出来, 放在一个方法里,并为这个方法注解@BeforeClass。意思是在测试类里所有用例运行之前,运行一次这个方法。例如创建数据库连接、读取文件等。

注意:方法名可以任意,但必须是public static void,即公开的、静态的、无返回值的。这个方法只会运行一次。

@AfterClass:跟@BeforeClass对应,在测试类里所有用例运行之后,运行一次。用于处理一些测试后续工作,例如清理数据,恢复现场。

注意:同样必须是public static void,即公开的、静态的、无返回值的。这个方法只会运行一次。

@Before:使用了该注解的方法在每个测试方法执行之前都要执行一次。主要用于一些独立于用例之间的准备工作。比如两个用例都需要读取数据库里的用户A信息,但第一个用例会删除这个用户A,而第二个用例需要修改用户A。那么可以用@BeforeClass创建数据库连接。用@Before来插入一条用户A信息。

注意:必须是public void,不能为static

@After :使用了该注解的方法在每个测试方法执行之后要执行一次。

@Runwith:即测试运行器,放在测试类名之前,用来确定测试类怎么运行的,当不指定这个注解时,使用默认Runner来运行测试代码,@RunWith(JUnit4.class)

常见的运行器有:

(1)@RunWith(Parameterized.class):参数化运行器,配合@Parameters使用JUnit的参数化功能。

(2)@RunWith(Suite.class)

@SuiteClasses({ATest.class,BTest.class,CTest.class})

测试集运行器配合使用测试集功能。

(3)@RunWith(JUnit4.class):JUnit 4的默认运行器

(4)@RunWith(JUnit38ClassRunner.class):用于兼容junit3.8的运行器

(5)一些其它运行器具备更多功能。例如@RunWith(SpringJUnit4ClassRunner.class)集成了Spring的一些功能。

@Parameters:用于JUnit的参数化功能,用来标记准备数据的方法。

注意:该方法需要满足一定的要求:

(1)该方法必须为public static

              (2)该方法返回值必须为java.util.Collection类型

              (3)该方法的名字不做要求

              (4)该方法没有参数

参数化测试

为了保证单元测试的严谨性,我们模拟了不同的测试数据来测试方法的处理能力,为此我们编写了大量的单元测试方法。而这些测试方法大同小异:代码结构都是相同的,不同的仅仅是测试数据和期望值。为了降低代码的冗余,JUnit 4提供了参数化测试,即只写一个测试方法,把这若干种情况作为参数传递进去,一次性的完成测试。

JUnit 4参数化测试的五个步骤:

     (1)为准备使用参数化测试的测试类指定特殊的运行器org.junit.runners.Parameterized。

     (2)为测试类声明几个变量,分别用于存放期望值和测试所用数据。

     (3)为测试类声明一个带有参数的公共构造函数,并在其中为第二个环节中声明的几个变量赋值。

     (4)为测试类声明一个使用注解 org.junit.runners.Parameterized.Parameters饰的,返回值为java.util.Collection的公共静态方法,并在此方法中初始化所有需要测试的参数对。

    (5)编写测试方法,使用定义的变量作为参数进行测试。

Demo如下:

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
@RunWith(Parameterized.class)
public class SquareTest {
 
    private static Calculator calculator = new Calculator();
 
    private int param;//参数
 
    private int result;//期望值
 
    // 准备数据 
    @Parameters 
    public static Collection data() {
        return Arrays.asList(new Object[][]{{2, 4},{0, 0},{-3, 9}});
    }
 
    //构造函数,对变量进行初始化
    public SquareTest(int param, int result) {
        this.param = param;
        this.result = result;
    }
 
    @Test 
    public void square() {
        calculator.square(param);
        assertEquals(result, calculator.getResult());
    }
}

打包测试

在一个项目中,只写一个测试类是不可能的,我们会写出很多很多个测试类。可是这些测试类必须一个一个的执行,也是比较麻烦的事情。鉴于此,JUnit为我们提供了打包测试的功能,将所有需要运行的测试类集中起来,一次性的运行完毕,大大的方便了我们的测试工作。具体代码如下:

1
2
3
4
@RunWith(Suite.class)
@Suite.SuiteClasses({ CalculatorTest.class,SquareTest.class})
public class AllCalculatorTests{
}

大家可以看到,这个功能也需要使用一个特殊的Runner,因此我们需要向@RunWith注解传递一个参数Suite.class。同时,我们还需要另外一个注解@Suite.SuiteClasses,来表明这个类是一个打包测试类。我们把需要打包的类作为参数传递给该注解就可以了。有了这两个注解之后,就已经完整的表达了所有的含义,因此下面的类已经无关紧要,随便起一个类名,内容全部为空既可。

异常测试

在JUnit 4之前,对错误的测试,我们只能通过fail来产生一个错误,并在try块里面assertTrue(true)来测试。现在,可以通过@Test 注解中的expected属性来测试异常。expected属性的值是一个异常的类型。

Demo如下:

1
2
3
4
@Test(expected=ArithmeticException.class)
public void testDivide() {
    new Calculator().divide(6, 0);
}

限时测试

对于那些逻辑很复杂,循环嵌套比较深的程序,很有可能出现死循环,因此一定要采取一些预防措施。限时测试是一个很好的解决方案。我们给这些测试方法设定一个执行时间,超过了这个时间,他们就会被系统强行终止,并且系统还会向你汇报该方法结束的原因是因为超时,这样你就可以发现这些Bug了。要实现这一功能,只需要给@Test 注解加一个timeout属性,该注解传入了一个时间(毫秒)给测试方法,如果测试方法在指定的时间之内没有运行完,则测试失败。

Demo如下:

1
2
3
4
@Test(timeout=1000)
public void testDeathLoop() {
    new Calculator().deathLoop();
}

单元测试运行结果:java.lang.Exception: test timed out after 1000 milliseconds

at test.Calculator.deathLoop(Calculator.java:25)

at test.CaculatorTest.testDeathLoop(CaculatorTest.java:26)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

Juniti学习总结的更多相关文章

  1. 从直播编程到直播教育:LiveEdu.tv开启多元化的在线学习直播时代

    2015年9月,一个叫Livecoding.tv的网站在互联网上引起了编程界的注意.缘于Pingwest品玩的一位编辑在上网时无意中发现了这个网站,并写了一篇文章<一个比直播睡觉更奇怪的网站:直 ...

  2. Angular2学习笔记(1)

    Angular2学习笔记(1) 1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之 ...

  3. ABP入门系列(1)——学习Abp框架之实操演练

    作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...

  4. 消息队列——RabbitMQ学习笔记

    消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...

  5. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  6. Unity3d学习 制作地形

    这周学习了如何在unity中制作地形,就是在一个Terrain的对象上盖几座小山,在山底种几棵树,那就讲一下如何完成上述内容. 1.在新键得项目的游戏的Hierarchy目录中新键一个Terrain对 ...

  7. 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:祝大家新年快乐,这次带来<D ...

  8. 菜鸟Python学习笔记第一天:关于一些函数库的使用

    2017年1月3日 星期二 大一学习一门新的计算机语言真的很难,有时候连函数拼写出错查错都能查半天,没办法,谁让我英语太渣. 关于计算机语言的学习我想还是从C语言学习开始为好,Python有很多语言的 ...

  9. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

随机推荐

  1. 笔记三、apache搭建gitweb【转】

    参考文章:     http://www.latelee.org/using-gnu-linux/ubuntu-apache-gitweb.html     http://blog.csdn.net/ ...

  2. flex 4 写皮肤

    皮肤容器:s:SparkSkin 主机组件:  [HostComponent("spark.components.Panel")] 绘制: <s:Group left=&qu ...

  3. 命令 crontab

    crontab命令选项基本只有对用户操作的选项: -u 指定一个用户 -l 列出某个用户的任务计划 -r 删除某个用户的任务 -e 编辑某个用户的任务 所以,要查看所有用户的,只能根据/etc/pas ...

  4. [LintCode]perfect-squares(DP)

    题目链接:http://www.lintcode.com/zh-cn/problem/perfect-squares/ 就是求最小价值的完全背包,初始化dp[i]=i,假设全是1的时候是最多的,之后就 ...

  5. maven3实战之仓库(快照版本)

    maven3实战之仓库(快照版本) ---------- 在Maven的世界中,任何一个项目或者构件都必须有自己的版本.版本的值可能是1.0.0,1.3-alpha-4,2.0,2.1-SNAPSHO ...

  6. XML Schema使用技巧——unique

    XML Schema使用技巧——unique   XML Scheam允许指定某个元素或属性的值在一定得范围内是唯一的.为了指定元素或属性值的唯一性,可以使用<xs:unqiue>元素,使 ...

  7. SPOJ ARCTAN (数论) Use of Function Arctan

    详细的题解见这里. 图片转自上面的博客 假设我们已经推导出来x在处取得最小值,并且注意到这个点是位于两个整点之间的,所以从这两个整数往左右两边枚举b就能找到b+c的最小值. 其实只用往一边枚举就够了, ...

  8. HDU 4324 (拓扑排序) Triangle LOVE

    因为题目说了,两个人之间总有一个人喜欢另一个人,而且不会有两个人互相喜欢.所以只要所给的图中有一个环,那么一定存在一个三元环. 所以用拓扑排序判断一下图中是否有环就行了. #include <c ...

  9. LA 3177 长城守卫

    n为偶数的时候比较简单,就是相邻两个守卫的礼物和的最大值. 首先这是个下限,其次这个值也满足题目要求,所以这就是答案了. 当n为奇数的时候上限是守卫索要礼物的最大值的三倍. 这也很容易理解,比如n=5 ...

  10. POJ 2069 Super Star

    模拟退火. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm& ...