标签:
JUnit4对于JUnit3来说是一个历史性的改革。因为JUnit4引入了注解(annotation),通过解析注解就可以为测试提供相应的信息,抛弃JUnit3使用命名约束以及反射机制的方法。但是JUnit4.x与JUnit3.8向后是兼容的。
预备知识点:
源文件夹:在eclipse中在项目中,右键新建选项中有一个源文件夹(Source folder)。其与普通文件夹的不同点表现在,他的图标是十字型的包裹图案。
源文件夹的特点:在源文件夹中的文件会自动转换为class文件存在于当前项目的bin目录中。
在eclipse中可以在需要测试的类文件上右击->新建->JUnit测试用例->创建测试用例(可以选择版本,文件夹路径,以及生成的其它细节)
计算机并不能准确地表示所有的浮点数,通常都会有一些偏差。因此如果用断言来比较浮点数,则需要制定一个额外的误差参数(tolerance)。
建议:
junit3和junit4的使用区别:
如何尽量提高测试代码的兼容性:
测试代码需要做的事情:
推荐图书:《单元测试之道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的运行结果:在上面代码的基础上进行的更改:
/**
* 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......注意:
Junit4采用注释的机制,所以名字的命名并不那么重要了,但是最好规范一下。
命名规范:测试方法以Test开头
在JUnit4中可以有setUp和tearDown方法,但是测试方法的时候不会被执行。
在JUnit4.x中想直接使用Assert方法,则需要静态导入Assert:import static org.junit.Assert.*;
在JUnit4.x中测试类可以是一个普通类,也可以去继承一个类或者实现一个接口,要实现测试,只需要在要测试的方法之前加上@Test注释。
常用注解:
@Test可以有两个参数:
一个测试类单元测试的执行顺序为:
@BeforeClass –> @Before –> @Test –> @After –> @AfterClass
每一个测试方法的调用顺序为:
@Before –> @Test –> @After
通过测试组件测试多个类:
指定测试组件使用@RunWith
JUnit4新增的两个断言:
镜像网站:http://hamcrest.org/
目的:增强JUnit,用一些语义通俗的方法来进行测试。要使用JUnit中的assertThat来进行断言。
需要静态导入Matchers包(import static org.hamcrest.Matchers.*;),否则就需要通过函数名称名称来调用了。
测试的具体方面:Right-BICEP
无论如何,必须确定代码所做的和你所期望的一致。我们需要尽可能的从需求说明中获取信息,来全面设计测试方法,有时候文档是不明了的或者不完整的,至少我们可以自己发明一些需求来。从客户角度来看问题,而且要根据用户的反馈来调整自己的假设。在代码的整个生命周期中,“正确”的定义可能会不断在改变。
针对有大量测试数据的测试,我们会考虑用一个独立的数据文件来存储这些测试数据,然后让单元测试读取该文件。这是一个很好地选择,但是测试数据很有可能是不正确的,实际上测试数据比代码更有可能出错。因此当测试数据显示错误发生的时候,我们应该在怀疑代码之前先对测试数据检查两三遍。
另外,还有一些值得考虑的:代码本身是否并没有测试任何异常的情况。要实现这个功能,需要怎么来做呢?
一个原则是:对于验证被测方法是正确的这件事情,如果某些做法能够使它更加容易,那么就采纳它吧。
<2>边界条件(CORRECT Boundary Conditions)
找边界条件是做单元测试中最有价值的工作之一,因为bug一般就出现在边界上。
一些需要我们考虑的条件有:
下面是测试边界接条件所需要考虑的几大反面:
<3>检查反向关联
对于一些方法,我们可以使用反向的逻辑关系来验证他们。
例如:我们可以用对结果进行平方的方式来检查一个计算平方根的函数,判断测试结果是否和元数据是否接近;为了检查某条记录是否成功地插入了数据库,你也可以通过查询这条记录来验证。等等
需要注意的是:当你同时编写了原方法和反向测试时,一些bug可能会被在连个函数中都出现的错误所覆盖。在可能的情况下,应该使用不同的原理来编写反向测试。
<4>使用其他手段来实现交叉检查
通常来说,计算一个量会有一种以上的算法。我们可能基于效率或者其他特性来选择算法。但是测试中我们没必要考虑这些,所以我们可以用剩下的算法中的一个来交叉检测结果。
<5>强制产生错误条件
真实世界中,错误总是会发生:磁盘会满,网络连接会断开,电子邮件会多的像掉进了黑洞,而长须会崩溃。你应该通过强制引发错误,来测试你的代码是如何处理所有这些真实世界中的问题的。
我们存在的环境因素有:
<6>性能特性
一个检查起来会很有益处的部分是性能特性,而不是性能本身。
简介:mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。
借助于mock对象,我们就可以解决上面的所有问题。在使用mock对象进行测试的时候,总共有3个关键步骤,分别是:
因为被测试代码只会通过接口来引用对象,所以它完全可以不知道它引用的究竟是真实对象还是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》
标签:
原文地址:http://blog.csdn.net/fanxiaobin577328725/article/details/52549479