说起单元测试,刚毕业或者没毕业的人可能大多停留在课本讲述的定义阶段,至于具体是怎么定义的,估计也不会有太多人记得。我们的教育总是这样让人“欣 慰”。那么什么是单元测试呢?具体科学的定义咱就不去关心了,其实每个写代码的人都在时刻进行着单元测试,除非你从来不验证自己写的代码能否达到预期目 的,而是直接写完就完事儿了,连run一下都不进行。

单元测试说的直白一点,就是验证写得一段代码是否正确,可能是一个类,可能是一个函数,甚至可能是一个循环。为了测试的方便,我们一般直接就在写好的可运 行代码中直接进行测试,看到控制台输出了预想的结果或者抛出了异常。但是进入了公司,这样的测试方法极不专业也不不容易复现测试环境。那么可能需要专门写 一个测试类,调用你想测试的代码单元,然后进行测试。但是这样每次都需要新建类,编写测试用例,相当之麻烦。

说了这么多,福利来了。单元测试工具——JUnit。协助我们进行单元测试,提供诸多便利。下面介绍如何在Eclipse中利用JUnit进行单元测试。

假如,我们编写了一个Calculator,提供一些简单的计算器功能。代码如下,故意留一些bug。

 1 package org.logback.test;
2
3 public class Calculator {
4
5 private static int result;
6 // 静态变量,用于存储运行结果
7
8 public void add(int n) {
9
10 result = result + n;
11
12 }
13
14 public void substract(int n) {
15
16 result = result - 1; //Bug: 正确的应该是 result = result-n
17
18 }
19
20 public void multiply(int n) {
21
22 } // 此方法尚未实现
23
24 public void divide(int n) {
25
26 result = result / n;
27
28 }
29
30 public void square(int n) {
31
32 result = n * n;
33
34 }
35
36 public void squareRoot(int n) {
37
38 for (; ;) ; //Bug : 死循环
39
40 }
41
42 public void clear() { // 将结果清零
43
44 result = 0;
45
46 }
47
48 public int getResult() {
49
50 return result;
51
52 }
53 }

那么要对这个类在现有开发程度下进行单元测试了,方法很简单,首先在该类所属的工程名上右键进入Properties。

在弹出的Properties窗口,左侧选择Java Build Path,然后右侧选择Libraries标签卡,最后选择Add Library。

在弹出的Add Library窗口中,选择JUnit点击Next,然后在下拉菜单中选择JUnit4,点击Finish。

这样JUnit就被引入了项目的Libraries中,点击OK。在要进行测试的那个类上右键,选择new→JUnit Test Case。

在弹出的新建窗口中按如下设置,具体含义稍后讲解

这里可以选择将测试类放在专门的测试包中,并且给测试类起一个显而易见的名字。选择Next,然后进入了下图。

此处是选择要测试的方法,假如我们只测试加减乘除4个方法,则勾选对应的4个方法,点击Finish。则自动生成了一个测试类,不过我们仍需对此类进行一定的修改,将该测试类最终修改为如下代码

 1 package org.logback.test;
2
3 import static org.junit.Assert.*;
4
5 import org.junit.After;
6 import org.junit.AfterClass;
7 import org.junit.Before;
8 import org.junit.BeforeClass;
9 import org.junit.Ignore;
10 import org.junit.Test;
11
12 public class CalculatorTest {
13
14 private static Calculator example = new Calculator();
15
16 @Before//在每个测试方法执行前先执行的方法
17 public void setUp() throws Exception {
18 example.clear();
19 }
20
21 @After//在每个测试方法执行后立刻执行的方法
22 public void setDown(){
23 System.out.println("over");
24 }
25
26 @BeforeClass //在类加载的时候调用的方法,必须public和static的,只调用一次
27 public static void start(){
28 System.out.println("start class");
29 }
30
31 @AfterClass //在类结束的时候调用的方法,必须public和static的,只调用一次
32 public static void destory(){
33 System.out.println("destory class");
34 }
35
36 @Test
37 public void testAdd() {
38 example.add(2);
39 example.add(3);
40 assertEquals(5, example.getResult());
41 }
42
43 @Test
44 public void testSubstract() {
45 example.add(10);
46 example.substract(2);
47 assertEquals(8, example.getResult());
48 }
49
50 @Ignore//因该方法暂未实现而忽略测试
51 @Test
52 public void testMultiply() {
53 fail("Not yet implemented");
54 }
55
56 @Test
57 public void testDivide() {
58 example.add(8);
59 example.divide(2);
60 assertEquals(4, example.getResult());
61 }
62
63 @Test(timeout = 1000)//设置时间限制,单位是毫秒,超时即算测试失败
64 public void testsquareRoot(){
65 example.squareRoot(4);
66 assertEquals(2, example.getResult());
67 }
68
69 @Test(expected = ArithmeticException.class)//测试是否能如期抛出该异常
70 public void divideByZero(){
71 example.divide(0);//除数为0,如能正确抛出异常,则测试通过,否则测试失败
72 }
73 }

每个方法都有注释,以标明其具体用途。

为了要测试Calculator的功能,所以需要先创建一个对应的实例,就如14行所做的那样。代码中出现了很多@开头的东西,下面简单介绍一下。以@开头的称为标注,是JDK1.5引入的特性,简介一下JUnit中常用的标注的含义:

@Test 标注的方法为测试方法,包含属性timeout(用于设置时间限制,以毫秒为单位,超过限制时间,该测试则以失败返回)、expected(设置此处应该抛出的异常,如果真抛出了该异常,则测试成功,否则失败)

@Before  标注的方法会在每个测试方法执行前先执行一次

@After 标注的方法会在每个测试方法执行结束后执行一次

@BeforeClass  标注的方法会在类加载的时候执行一次,且仅此一次,该方法必须是public和static的

@AfterClass   标注的方法会在类销毁的时候执行一次,且仅此一次,该方法必须是public和static的

@Ignore  标注的方法表示因为要测试的方法仍未实现而忽略测试

@Parameters  标注的方法用于定义测试数据集合,一般用来给一个测试方法传递多组测试数据

以上标注都是用来标注方法的,下面介绍两个用来标注类的:

@RunWith(classname.class)  指定此测试采用什么运行器,如果不设置,则采用默认的运行器,就像我们上一个例子中那样。

@Suite.SuiteClasses({

TestClassName1.class,

TestClassName2.class,

...

})   打包测试,有时会遇到同一个类的测试类有很多个,逐个运行测试太麻烦了,那就通过这种方式将所有要运行的测试类一起运行。文章后面会给出例子。

介绍完标注之后,再来看一下测试方法中用到的assertEquals的功能。该方法有两个参数,第一个是预期的值,第二个是传递给方法的结果,用以比对方法处理后的结果与预期是否一致,因此来返回测试是否成功还是失败。

用之前的代码进行测试,步骤如下:

在类中右键Run As → JUnit Test

可以看到左侧JUnit标签出现如下图所示结果:

最上方的深红色进度条,表示有测试方法返回失 败。然后列出了6个测试方法,蓝色X表示预期与实际结果不相同,红色X表示超过了限制条件(此处是超时了,因为测试方法调用的方法里面有死循环),绿色√ 表示该测试方法成功,灰色/表示该测试方法被忽略。点击列表中对应的方法名时,下方Failure Trace会给出错误信息。

上述例子是针对测试的方法不需要多组数据的情况。OK,今天先这么多!改天继续~

PS: 我存在过,我遇见过,我失败过。 有些路,明明有坑却从没人放警示牌。有些事,明明是错的却没人去管。有些话,明明应该告诉后来人却没人去说。 既然没人做,那就我来吧。希望我曾经历过的挫折不再重现于后来人。希望传承能够不是只挂在嘴边。希望人模人样的“人”能够真正做人。

Java知识积累——单元测试和JUnit(一)的更多相关文章

  1. java知识积累——单元测试和JUnit(二)

    首先来复习一下几个重要知识点,然后接着进行一些介绍.在上一篇文章中,我曾经贴过下面这张图片: 在Which method stubs would you like to create?这里,现在结合4 ...

  2. JAVA知识积累 给HttpClient添加Socks代理

    本文描述http client使用socks代理过程中需要注意的几个方面:1,socks5支持用户密码授权:2,支持https:3,支持让代理服务器解析DNS: 使用代理创建Socket 从原理上来看 ...

  3. Java知识积累3-XML的DOM解析修改和删除方法

    import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder;import jav ...

  4. Java知识积累-XML的DOM解析修改和删除方法

    import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder;import jav ...

  5. Java知识积累2-StringReverse实现文字(单词)倒叙输出

    package String; import java.util.Stack;import java.util.StringTokenizer; public class StringReverse ...

  6. Java知识积累1-StringAlign实现文字居中左右对齐

    import java.text.*;public class StringAlign extends Format{ public static final int JUST_LEFT='l'; / ...

  7. 项目积累——JAVA知识积累

    调用天气: <iframe src="http://www.thinkpage.cn/weather/weather.aspx?uid=&c=CHXX0008&l=zh ...

  8. JAVA知识积累 JSP第一篇【JSP介绍、工作原理、生命周期、语法、指令、行为】

    什么是JSP JSP全名为Java Server Pages,java服务器页面.JSP是一种基于文本的程序,其特点就是HTML和Java代码共同存在! 为什么需要JSP JSP是为了简化Servle ...

  9. Java单元测试框架 JUnit

    Java单元测试框架 JUnit JUnit是一个Java语言的单元测试框架.它由Kent Beck和Erich Gamma建立,逐渐成为源于KentBeck的sUnit的xUnit家族中为最成功的一 ...

随机推荐

  1. DBus通讯

    linux下进程间通信的方式主要有Pipe(管道),FIFO(命名管道),信号,共享内存,消息队列,信号灯等,这些方式各有 各得特点,如管道是linux下命令行中常用的,用于父子进程的通信.但是这些通 ...

  2. 【http】http/1.1 八种请求方式

    OPTIONS 返回服务器针对特定资源所支持的HTTP请求方法.也可以利用向Web服务器发送'*'的请求来测试服务器的功能性. HEAD 向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回 ...

  3. MAC 平台 QT编写iphone程序,加载iphone模拟器失败解决办法

    本日这么多年一直做C++开发,最近要做QT项目,被QT做界面的新特性所吸引.QSS QML的确是亮点. 还有一个就是跨平台这方面,自己玩了玩. 用的QT 的开发包是在官网上下载 qt-opensour ...

  4. MAC 升级到10.10(OS X Yosemite)下apache+php的配置问题

    MAC升级到最新系统后 本地测试的站点不能正常运行,其原因是mac系统升级后 他的apache的版本也随之升级了版本 Server version: Apache/2.4.9 (Unix) Serve ...

  5. Java对象的序列化与反序列化

    序列化与反序列化 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程.一般将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等.在网络传输过程中,可以是字节或是 ...

  6. Leetcode-Read N Characters Given Read4 II

    The API: int read4(char *buf) reads 4 characters at a time from a file. The return value is the actu ...

  7. Careercup - Google面试题 - 5732809947742208

    2014-05-03 22:10 题目链接 原题: Given a dictionary, and a list of letters ( or consider as a string), find ...

  8. struts2 ,web.xml中配置为/*.action,运行报错Invalid <url-pattern> /*.action in filter mapp

    首先,修改成: <filter-mapping>  <filter-name>struts2</filter-name>  <url-pattern>/ ...

  9. cg 到hlsl的转换

    http://msdn.microsoft.com/en-us/library/windows/desktop/ff471376(v=vs.85).aspx http://gamedev.stacke ...

  10. What are Scopes?

    scope is an object that refers to the application model. It is an execution context for expressions. ...