单元测试——junit

一、前言

JUnit4对于JUnit3来说是一个历史性的改革。因为JUnit4引入了注解(annotation),通过解析注解就可以为测试提供相应的信息,抛弃JUnit3使用命名约束以及反射机制的方法。但是JUnit4.x与JUnit3.8向后是兼容的。

官网:http://junit.org/junit4/

预备知识点:

源文件夹:在eclipse中在项目中,右键新建选项中有一个源文件夹(Source folder)。其与普通文件夹的不同点表现在,他的图标是十字型的包裹图案。

源文件夹的特点:在源文件夹中的文件会自动转换为class文件存在于当前项目的bin目录中。

在eclipse中可以在需要测试的类文件上右击->新建->JUnit测试用例->创建测试用例(可以选择版本,文件夹路径,以及生成的其它细节)

计算机并不能准确地表示所有的浮点数,通常都会有一些偏差。因此如果用断言来比较浮点数,则需要制定一个额外的误差参数(tolerance)。

建议:

  1. 不建议使用eclipse集成的JUnit,因为其版本是固定的,相对而言可能一些新特性是不支持的。
  2. 测试代码放在与src同级的另外一个源文件夹中
  3. 测试文件的路径结构应与被测试的源文件相同
  4. 测试文件的命名:Test+源文件名称

junit3和junit4的使用区别:

  1. 在JUnit3中需要继承TestCase类,但在JUnit4中已经不需要继承TestCase
  2. 在JUnit3中需要覆盖TestCase中的setUp和tearDown方法,其中setUp方法会在测试执行前被调用以完成初始化工作,而tearDown方法则在结束测试结果时被调用,用于释放测试使用中的资源,而在JUnit4中,只需要在方法前加上@Before,@After
  3. 在JUnit3中对某个方法进行测试时,测试方法的命令是固定的,例如对addBook这个方法进行测试,需要编写名字为testAddBook的测试方法,而在JUnit4中没有方法命令的约束,在方法的前面加上@Test,这就代表这个方法是测试用例中的测试方法
  4. 新的断言assertThat
  5. @BeforeClass 和 @AfterClass 。在JUnit3,如果所有的test case仅调用一次setUp()和tearDown()需要使用TestSetup类
  6. 测试异常处理@Test(expected = DataFormatException.class)
  7. 设置超时@Test(timeout = 1000)
  8. 忽略测试@Ignore
  9. 集成测试

如何尽量提高测试代码的兼容性:

  • JUnit4中初始化函数命名为setUp(),释放资源的函数命名为tearDown()
  • JUnit4中测试函数一test
  • 为了在JUnit4中像JUnit3中直接使用assert(断言),我们要静态导入Assert类(import static org.junit.Assert.*;)

测试代码需要做的事情:

  • 准备测试所需要的各种条件(创建所有必须的对象,分配必要的资源等等)
  • 调用要测试的方法
  • 验证被测试方法的行为和期望是否一致
  • 完成后清理各种资源

二、JUnit3使用

推荐图书:《单元测试之道Java版:使用JUnit

随书代码:http://download.csdn.net/detail/fanxiaobin577328725/9632002

JUnit3采用的是反射机制,所以对名字的命名非常重要。

1.测试方法必须在原方法的方法首部添加Test,测试类没有这样强制要求。

2.测试类必须继承TestCase。

3.测试方法覆盖setUp和tearDown方法来初始化和释放资源。(测试每一个方法都会执行一次setUp和tearDown方法

OneTimeSetUp是什么?没关系向下看就可以了,下面将给出详细解释。

断言方法:(因为继承了TestCase,而TestCase继承了Assert类,所以直接使用断言)

基本上:下列函数的第一个参数可以是可选的信息参数。

常用断言方法
常用方法 解释
assertArrayEquals(expecteds, actuals) 查看两个数组是否相等
assertEquals(expected, actual) 查看两个对象是否相等,类似于字符串比较使用的equals()方法
assertEquals(String message,expected, actual) 与上面一样,就是在出错时显示message信息。
assertNotEquals(first, second) 查看两个对象是否不相等。
assertNull(object) 查看对象是否为空
assertNotNull(object) 查看对象是否不为空
assertSame(expected, actual) 查看两个对象的引用是否相等。类似于使用“==”比较两个对象
assertNotSame(unexpected, actual) 查看两个对象的引用是否不相等。类似于使用“!=”比较两个对象
assertTrue(condition) 查看运行结果是否为true
assertFalse(condition) 查看运行结果是否为false
assertThat(actual, matcher) 查看实际值是否满足指定的条件
fail() 让测试失败

默认情况下,JUnit会自动运行所有的test...方法。然而任何测试类都能包含一个名为suite的静态方法:

public static Test suite() {
    TestSuite suite = new TestSuite();
  //想要测试的代码 
<pre name="code" class="java">  //.......
  return suite;
}

suite方法不仅可以调用当前测试类中的指定测试函数,还可以调用其他测试类以及其他测试类中的suite方法。

示例:

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * A brute-force solution to the Travelling Salesman Problem.
 *
 * It will run in exponential time.
 *
 * Better solutions use genetic algorithms and such.
 */

public class TSP {

  /**
   * For the top numCities in our territory, compute the shortest path
   * and return thr total number of miles in that path.
   */
  public int shortestPath(int numCities) {
    // Ha!  Mock object!
    switch (numCities) {
    case 50: return 2300;
    case 5: return 140;
    case 10: return 586;
    }
    return 0;
  }

  /**
  * Load the cities for the given territory and lock them
  */
  public void loadCities(String name) {
  }

  /**
  * Relase the lock on cities in this territory
  */
  public void releaseCities() {
  }

}

测试代码:(TestClassTwo)

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

import junit.framework.*;

public class TestClassTwo extends TestCase {

  public TestClassTwo(String method) {
    super(method);
  }

  // This one takes a few hours...
  public void testLongRunner() {
    TSP tsp = new TSP(); // Load with default cities
    assertEquals(2300, tsp.shortestPath(50)); // top 50
  }

  public void testShortTest() {
    TSP tsp = new TSP(); // Load with default cities
    assertEquals(140, tsp.shortestPath(5)); // top 5
  }

  public void testAnotherShortTest() {
    TSP tsp = new TSP(); // Load with default cities
    assertEquals(586, tsp.shortestPath(10)); // top 10
  }

  public static Test suite() {
    TestSuite suite = new TestSuite();
    // Only include short tests
    suite.addTest(
          new TestClassTwo("testShortTest"));
    suite.addTest(
          new TestClassTwo("testAnotherShortTest"));
    return suite;
  }

}

TestClassTwo的运行结果:

测试结果显示:testLongRunner()没有运行。

测试代码:(TestClassOne)

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

import junit.framework.*;

public class TestClassOne extends TestCase {

  public TestClassOne(String method) {
    super(method);
  }

  public void testAddition() {
    assertEquals(4, 2+2);
  }

  public void testSubtraction() {
    assertEquals(0, 2-2);
  }

}

测试代码:(TestClassComposite)

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

import junit.framework.*;

public class TestClassComposite extends TestCase {

  public TestClassComposite(String method) {
    super(method);
  }

  static public Test suite() {
    TestSuite suite = new TestSuite();
    // Grab everything:
    suite.addTestSuite(TestClassOne.class);
    // Use the suite method:
    suite.addTest(TestClassTwo.suite());
    return suite;
  }

}

TestClassComposite的运行结果:

测试结果显示:其执行了TestClassOne中的所有测试方法,执行了TestClassTwo中的suite方法。

上面我们了解到每一个方法执行前后都会有一个setUp和tearDown方法执行,然而suite的初始化以及清理工作与方法是分开的。过程相对复杂了点,需要提供所需测试的一个suite(无论通过什么样的方法)并且把它包装进一个TestSetup对象。

在上面代码的基础上进行的更改:

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

import junit.framework.*;
import junit.extensions.*;

public class TestClassTwo extends TestCase {

    private static TSP tsp;

    public TestClassTwo(String method) {
        super(method);
    }

    // This one takes a few hours...
    public void testLongRunner() {
        System.out.println("testLongRunner method running");
        assertEquals(2300, tsp.shortestPath(50));
    }

    public void testShortTest() {
        System.out.println("testShortTest method running");
        assertEquals(140, tsp.shortestPath(5));
    }

    public void testAnotherShortTest() {
        System.out.println("testAnotherShortTest method running");
        assertEquals(586, tsp.shortestPath(10));
    }

    public static Test suite() {
        TestSuite suite = new TestSuite();
        // Only include short tests
        suite.addTest(new TestClassTwo("testShortTest"));
        suite.addTest(new TestClassTwo("testAnotherShortTest"));

        TestSetup wrapper = new TestSetup(suite) {
            protected void setUp() {
                oneTimeSetUp();
            }

            protected void tearDown() {
                oneTimeTearDown();
            }
        };

        return wrapper;
    }

    public static void oneTimeSetUp() {
        // one-time initialization code goes here...
        System.out.println("suite_up......");
        tsp = new TSP();
        tsp.loadCities("EasternSeaboard");
    }

    public static void oneTimeTearDown() {
        // one-time cleanup code goes here...
        System.out.println("suite_down......");
        tsp.releaseCities();
    }

    @Override
    protected void setUp() throws Exception {
        // TODO 自动生成的方法存根
        System.out.println("setUp.....");
        super.setUp();
    }

    @Override
    protected void tearDown() throws Exception {
        // TODO 自动生成的方法存根
        System.out.println("tearDown.....");
        super.tearDown();
    }

}

运行结果:

suite_up......
setUp.....
testShortTest method running
tearDown.....
setUp.....
testAnotherShortTest method running
tearDown.....
suite_down......

注意:

你可以在同一个类中同时使用方法和suite的setup()和teardown()。

三、JUnit4使用

Junit4采用注释的机制,所以名字的命名并不那么重要了,但是最好规范一下。

命名规范:测试方法以Test开头

在JUnit4中可以有setUp和tearDown方法,但是测试方法的时候不会被执行。

在JUnit4.x中想直接使用Assert方法,则需要静态导入Assert:import static org.junit.Assert.*;

在JUnit4.x中测试类可以是一个普通类,也可以去继承一个类或者实现一个接口,要实现测试,只需要在要测试的方法之前加上@Test注释。

常用注解:

  • @Before:在每个测试之前运行的代码
  • @After :在每个测试之后运行的代码
  • @Test:测试代码
  • @Ignore:忽略的测试方法
  • @BeforeClass:针对所有测试,只执行一次,且必须为static void
  • @AfterClass:针对所有测试,只执行一次,且必须为static void
  • @RunWith:指定测试类使用某个运行器
  • @Parameters:指定测试类的测试数据集合
  • @Rule:允许灵活添加或重新定义测试类中的每个测试方法的行为
  • @FixMethodOrder:指定测试方法的执行顺序

@Test可以有两个参数:

  1. expected:检测方法是否抛出指定的异常(未抛出报错误)
  2. timeout:方法执行操作所耗费的毫秒数(超出指定时间报错误)

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

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

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

@Before –> @Test –> @After

通过测试组件测试多个类:

指定测试组件使用@RunWith

JUnit4新增的两个断言:

四、Hamcrest框架

镜像网站:http://hamcrest.org/

目的:增强JUnit,用一些语义通俗的方法来进行测试。要使用JUnit中的assertThat来进行断言。

需要静态导入Matchers包(import static org.hamcrest.Matchers.*;),否则就需要通过函数名称名称来调用了。

五、其它细节

1.测试

测试的具体方面:Right-BICEP

  • Right——结果是否正确?
  • B——是否所有的边界条件都是正确的?
  • I——能查一下反向关联吗?
  • C——能用其他手段交叉检查一下结果吗?
  • E——你是否可以强制错误条件发生?
  • P——是否满足性能要求?

<1>结果的正确性

无论如何,必须确定代码所做的和你所期望的一致。我们需要尽可能的从需求说明中获取信息,来全面设计测试方法,有时候文档是不明了的或者不完整的,至少我们可以自己发明一些需求来。从客户角度来看问题,而且要根据用户的反馈来调整自己的假设。在代码的整个生命周期中,“正确”的定义可能会不断在改变。

针对有大量测试数据的测试,我们会考虑用一个独立的数据文件来存储这些测试数据,然后让单元测试读取该文件。这是一个很好地选择,但是测试数据很有可能是不正确的,实际上测试数据比代码更有可能出错。因此当测试数据显示错误发生的时候,我们应该在怀疑代码之前先对测试数据检查两三遍。

另外,还有一些值得考虑的:代码本身是否并没有测试任何异常的情况。要实现这个功能,需要怎么来做呢?

一个原则是:对于验证被测方法是正确的这件事情,如果某些做法能够使它更加容易,那么就采纳它吧。

<2>边界条件(CORRECT Boundary Conditions)

找边界条件是做单元测试中最有价值的工作之一,因为bug一般就出现在边界上。

一些需要我们考虑的条件有:

  • 完全伪造或者不一致的输入数据,例如一个名为“!*W:X\&Gi/w->g/h#[email protected]”的文件。
  • 格式错误的数据,例如没有顶级域名的电子邮件地址,就像[email protected]这样的。
  • 空值或者不完整的值(如0.0.0. “”和null)
  • 一些与意料中的合理值想去甚远的数值。例如一个人的随书为10000岁
  • 如果需求的是一个不允许出现重复数值的list,但是传入的是一个存在重复数值的list。
  • 如果要求的是一个有序list,但是传入的是一个无序的list;或者反之。
  • 事情达到的次序是错误的,或者碰巧和期望的次序不一致。例如,在未登录系统之前,就尝试打印文档

下面是测试边界接条件所需要考虑的几大反面:

  • 一致性(Conformance)——值是否和预期的一致。
  • 顺序性(Ordering)——值是否如应该的那样,是有序或者无序的。
  • 区间性(Range)——值是否位于合理的最小值和最大值之内。
  • 依赖性(Reference)——代码是否引用了一些不在代码本身控制范围之内的外部资源。
  • 存在性(Existence)——值是否存在(例如,是否是非null,非0,在一个集合中等等)。
  • 基数性(Cardinatity)——是否恰好有足够的值?
  • 相对或者绝对的时间性(Time)——所有事情的发生是否是有序的?是否是在正确的时刻?是否恰好及时?

<3>检查反向关联

对于一些方法,我们可以使用反向的逻辑关系来验证他们。

例如:我们可以用对结果进行平方的方式来检查一个计算平方根的函数,判断测试结果是否和元数据是否接近;为了检查某条记录是否成功地插入了数据库,你也可以通过查询这条记录来验证。等等

需要注意的是:当你同时编写了原方法和反向测试时,一些bug可能会被在连个函数中都出现的错误所覆盖。在可能的情况下,应该使用不同的原理来编写反向测试。

<4>使用其他手段来实现交叉检查

通常来说,计算一个量会有一种以上的算法。我们可能基于效率或者其他特性来选择算法。但是测试中我们没必要考虑这些,所以我们可以用剩下的算法中的一个来交叉检测结果。

<5>强制产生错误条件

真实世界中,错误总是会发生:磁盘会满,网络连接会断开,电子邮件会多的像掉进了黑洞,而长须会崩溃。你应该通过强制引发错误,来测试你的代码是如何处理所有这些真实世界中的问题的。

我们存在的环境因素有:

  • 内存耗光
  • 磁盘用满
  • 时钟出问题
  • 网络不可用或者有问题
  • 系统过载
  • 调色板颜色数目有限
  • 显示分辨率过高或者过低

<6>性能特性

一个检查起来会很有益处的部分是性能特性,而不是性能本身。

2.测试原则

  1. 建议创建一个站们的source folder-->test来编写测试类代码
  2. 测试类的包应该保持和需要测试的类的一致性
  3. 测试单元中的每一个测试方法都必须可以独立运行,没有顺序,而且测试方法之间不能有任何的依赖性

3.Mock测试

简介:mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。

  • 真实对象具有不可确定的行为(产生不可预测的结果,如股票行情)
  • 真实对象很难被常见
  • 真实对象的某些行为很难出发(如网络错误)
  • 真实对象令程序的运行速度很慢
  • 真实对象有(或者是)用户界面
  • 测试需要询问真实对象他是如何被调用的(例如,测试可能需要验证某个回调函数是否被调用了)
  • 真实对象实际上并不存在(当需要和其他开发小组,或者新的硬件系统打交道的时候,这是一个普遍问题)

借助于mock对象,我们就可以解决上面的所有问题。在使用mock对象进行测试的时候,总共有3个关键步骤,分别是:

  1. 使用一个借口来描述这个对象
  2. 为产品代码实现这个接口
  3. 以测试为目的,在mock对象中实现这个接口

因为被测试代码只会通过接口来引用对象,所以它完全可以不知道它引用的究竟是真实对象还是mock对象。

下面是一个详细的示例:(具体讲解在《单元测试之道Java版:使用JUnit》这里不再详细叙述)

Environmental.java

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Various methods particular to our runtime environment
 */

public interface Environmental {
	public long getTime();
	// Other methods omitted...

	public void playWavFile(String name);

}

SystemEnvironment.java

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing" ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. Visit
 * www.PragmaticProgrammer.com
 */

public class SystemEnvironment implements Environmental {
	public long getTime() {
		return System.currentTimeMillis();
	}
	// other methods ...

	public void playWavFile(String name) {
		// Left as an exercise to the reader...
	}

}

MockSystemEnvironment.java

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing" ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. Visit
 * www.PragmaticProgrammer.com
 */

public class MockSystemEnvironment implements Environmental {
	private long current_time;
	private boolean playedWav = false;
	public long getTime() {
		return current_time;
	}

	public void setTime(long aTime) {
		current_time = aTime;
	}

	public void playWavFile(String filename) {
		playedWav = true;
	}

	public boolean wavWasPlayed() {
		return playedWav;
	}

	public void resetWav() {
		playedWav = false;
	}

	// ...
}

Checker.java

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

import java.util.Calendar;

public class Checker {

	public Checker(Environmental anEnv) {
		env = anEnv;
	}

	/**
	 * After 5 o'clock, remind people to go home by playing a whistle
	 */
	public void reminder() {
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(env.getTime());
		int hour = cal.get(Calendar.HOUR_OF_DAY);

		if (hour >= 17) { // 5:00PM
			env.playWavFile("quit_whistle.wav");
		}

	}

	// ...

	private Environmental env;
}

TestChecker.java

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

/**
 * Excerpted from the book, "Pragmatic Unit Testing"
 * ISBN 0-9745140-1-2
 * Copyright 2003 The Pragmatic Programmers, LLC.  All Rights Reserved.
 * Visit www.PragmaticProgrammer.com
 */

import junit.framework.*;
import java.util.Calendar;

public class TestChecker extends TestCase {

	public void testQuittingTime() {

		MockSystemEnvironment env = new MockSystemEnvironment();

		// Set up a target test time
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, 2004);
		cal.set(Calendar.MONTH, 10);
		cal.set(Calendar.DAY_OF_MONTH, 1);
		cal.set(Calendar.HOUR_OF_DAY, 16);
		cal.set(Calendar.MINUTE, 55);
		long t1 = cal.getTimeInMillis();

		env.setTime(t1);

		Checker checker = new Checker(env);

		// Run the checker
		checker.reminder();

		// Nothing should have been played yet
		assertFalse(env.wavWasPlayed());

		// Advance the time by 5 minutes
		t1 += (5 * 60 * 1000);
		env.setTime(t1);

		// Now run the checker
		checker.reminder();

		// Should have played now
		assertTrue(env.wavWasPlayed());

		// Reset the flag so we can try again
		env.resetWav();

		// Advance the time by 2 hours and check
		t1 += 2 * 60 * 60 * 1000;
		env.setTime(t1);

		checker.reminder();
		assertTrue(env.wavWasPlayed());
	}
}

测试Servlet

基于Web的Servlet需要容器(常用的是Tomcat)和浏览器,运行过程和环境相对复杂,这是一个交互的过程,看起来无法完成自动化的单元测试,幸运的是Mock对象可以解决这个问题。

(这部分没有理解透,这里还使用了easymock)

参考资料:

《单元测试之道Java版:使用JUnit》

Junit使用教程(二)

时间: 2024-08-29 12:17:10

单元测试——junit的相关文章

单元测试Junit

###<center> 单元测试Junit </center>###- - -1.**单元测试**:> ==单元测试==是软件之中对于最小的功能模块的的测试,其可以对最基本的软件构成单元来测试.> 需要注意的是:> >**测试用例是用来达到测试想要的预期结果,而不能测试出程序的逻辑错误**. 2.**JUnit**:>1.**Junit是基于断言机制的**.是用于编写可复用测试集的简单框架,是xUnit的一个子集.xUnit是一套基于测试驱动开发的测试

Android Day02-Android中单元测试(junit测试)&monkey测试

Android中junit测试有2种实现方式 第1种:一般Android工程的实现方式 1.在清单文件中添加2项内容 首先在AndroidManifest.xml中加入下面红色代码: <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.itcast.action" android:versionCode="1"  android:v

Java 单元测试Junit

@Test @Before @After 测试方法运行前执行Before动作(比如创建资源),运行后执行After动作(比如销毁资源) @BeforeClass @AfterClass 测试类运行前执行Before动作(比如创建资源),运行后执行After动作(比如销毁资源) Assert 对方法结果进行判断,是否等于希望值,是否为空等 表示测试通过不通过 Java 单元测试Junit,布布扣,bubuko.com

菜鸟学Java(二十一)——如何更好的进行单元测试——JUnit

测试在软件声明周期中的重要性,不用我多说想必大家也都非常清楚.软件测试有很多分类,从测试的方法上可分为:黑盒测试.白盒测试.静态测试.动态测试等:从软件开发的过程分为:单元测试.集成测试.确认测试.验收.回归等. 在众多的分类中,与开发人员关系最紧密的莫过于单元测试了.像其他种类的测试基本上都是由专门的测试人员来完成,只有单元测试是完全由开发人员来完成的.那么今天我们就来说说什么是单元测试,为什么要进行单元测试,以及如更好的何进行单元测试. 什么是单元测试? 单元测试(unit testing)

上课笔记_单元测试JUnit

单元测试  单元测试就是整合程序代码到系统的其余部分之前先测试以便找出程序代码中的bugs,单元测试是白盒测试: 有很多测试工具我们为什么要选择JUnit测试工具? 1. 开源 2. 使用简单 3. 可以扩展功能 MyEclipse集合了JUnit:这里通过导入jar包来实现. Junit4下载地址:http://pan.baidu.com/s/1kTLZa3X 我们一般在项目右击新建一个source foler :test  :(发布的时候test不会被发布) 新建包名和要测试的类的包名一样:

Java单元测试Junit的Annotation介绍

单元测试是开发者的业界良心 Java开发中常以Junit作为测试框架,而且Junit也成为Java社区测试方面的事实标准,可以百度一些看看Junit的相关介绍.目前Junit发展到了Junit4.x版本,相对之前的Junit3.x版本有着明显的变化就是使用了Annotation的方式来注解测试用例. 下面是关于Junit4.x的常用注解说明图: Java单元测试Junit的Annotation介绍

Java单元测试(Junit+Mock+代码覆盖率)---------转

Java单元测试(Junit+Mock+代码覆盖率) 原文见此处 单元测试是编写测试代码,用来检测特定的.明确的.细颗粒的功能.单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的. 单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代码修复.改进或重构之后的正确性. 一般来说,单元测试任务包括 接口功能测试:用来保证接口功能的正确性. 局部数据结构测试(不常用):用来保证接口中的数据结构是正确的 比如变量有无初始值 变量是否溢出 边界条件测试 变量没有赋值(即为NULL) 变

Android单元测试Junit (一)

1.在eclips中建立一个Android工程,具体信息如下: 2.配置单元测试环境,打开AndroidManifest.xml,具体代码如下所示: <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.milan.junit&quo

Java单元测试(Junit+Mock+代码覆盖率)

原文见此处 单元测试是编写测试代码,用来检测特定的.明确的.细颗粒的功能.单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的. 单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代码修复.改进或重构之后的正确性. 一般来说,单元测试任务包括 接口功能测试:用来保证接口功能的正确性. 局部数据结构测试(不常用):用来保证接口中的数据结构是正确的 比如变量有无初始值 变量是否溢出 边界条件测试 变量没有赋值(即为NULL) 变量是数值(或字符) 主要边界:最小值,最大值,无穷大(

java单元测试(Junit)

最基本的模块测试 1:首先创建一个java工程,在工程中创建一个被单元测试的Student数据类,如下: package UnitTest; public class Student { private String name; private String sex; private int high; private int age; private String school; public Student(String name, String sex, int high, int age