JUnit使用经验总结

经验一、不要在测试用例的构造函数中做初始化,而是在setUp()中


经验二、不要假定测试用例中测试的执行次序

一个JUnit 的测试用例类中可以包含多个测试,每个测试其实就是一个method。在下面的例子中有两个不同的测试,尽管testDoThisFirst()在位置上先于testDoThisSecond(),但不能就此假定testDoThisFirst()会先执行。

public class SomeTestCase extends TestCase{
public SomeTestCase(String testName){
super(testName);
}
public void testDoThisFirst(){
}
public void testDoThisSecond(){
}
}

由于JUnit 内部使用一个Vector 来存储所有的test,因此在不同的操作系统和Java 虚拟机上,test 的执行次序是不可预测的。
好的习惯是保持测试之间的独立性,使得它们在任何次序下执行的结果都是相同的。如果真得需要某些测试按照特定的次序执行,我们可以新建一个测试套装testsuite类,借助addTest方法来实现。如下例:

public static Testsuite(){
suite.addTest(new SomeTestCase(“testDoThisFirst”);
suite.addTest(new SomeTestCase(“testDoThisSecond”);
return suite;
}

这样我们可以确保JUnit先执行testDoThisFirst(),然后执行testDoThisSecond()。


经验三、测试要避免人工干预

如果某段测试代码需要人工干预,那至少有两个不良后果:一则不能被包括在自动测试中,比如夜间的回归测试;二则不能被重复执行,例如数据删除的测试不能做完删除就万事大吉,比较好的做法是自动补上删除掉的数据。经验二讲的是不同的测试要避免相关性,而经验三讲的其实就是测试要避免自相关。


经验四、在子类中调用父类的setUp() 和tearDown()

public class SomeTestCase extends AnotherTestCase {
// A connection to a database
private Database theDatabase;
public SomeTestCase (String testName) {
super (testName);
}
public void testFeatureX () {
}
public void setUp () {
// Clear out the database
theDatabase.clear ();
}
}

你发现其中的错误了吗?setUp()应该调用super.setUp() 以确保AnotherTestCase 中定义的环境被初
始化了。当然这也有例外,就是基类可以处理任意的测试数据。

经验五、不要硬编码数据文件的路径


经验六、把测试的代码和被测的代码放在同样的目录下

当我们把测试代码和被测的代码放在同一目录下时,我们就可以在编译被测代码的同时编译测试代码,从而确保两者是同步更新的。事实上当前的普遍做法,就是把单元测试视为Build 的一个环节。

经验七、正确命名测试

把测试用例命名为TestClassUnderTest。
比如如果被测的Class 是MessageLog,那么测试用例就叫TestMessageLog,这样做使得测试用例和被测的Class一一对应,而在测试用例中每个测试的method 就可以命名为
testLoggingEmptyMessage()
testLoggingNullMessage()
testLoggingWarningMessage()
testLoggingErrorMessage()
同样是为了说清楚测试的是什么。正确的命名可以帮助测试代码的阅读者了解每个测试的目的。



经验八、利用Junit 的自动异常处理书写简洁的测试代码

很多Junit 的初学者经常会写出类似下面的这些代码

public void exampleTest () {
try {
// do some test
} catch (SomeApplicationException e) {
fail ("Caught SomeApplicationException exception";
}
}

事实上在Junit 中使用try-catch 来捕获异常是没有必要的,Junit 会自动捕获异常。那些没有被捕获的异常就
被当成错误处理。所以上面的代码很冗余,完全可以写成下面等效却简洁得多的代码:

public void exampleTest () throws SomeApplicationException {
// do some test
}

更少的测试代码也更容易读懂更容易维护。

经验九、充分利用Junit 的assert/fail 方法

Junit 有丰富而灵活的assert/fail 方法,如何用好这些方法也是大有讲究的。比如下面的写法就不大好
assert (creds == 3);
不如写成
assertEquals (“The number of credentials should be 3”, 3, creds);
第二种写法不仅易于阅读,而且在执行时如果fail 也可以向测试人员提供更多的信息。
junit中的assert方法全部放在Assert类中,总结一下junit类中assert方法的分类。
1.assertTrue/False([String message,]boolean condition);
判断一个条件是true还是false。感觉这个最好用了,不用记下来那么多的方法名。
2.fail([String message,]);
失败,可以有消息,也可以没有消息。
3.assertEquals([String message,]Object expected,Object actual);
判断是否相等,可以指定输出错误信息。
第一个参数是期望值,第二个参数是实际的值。
这个方法对各个变量有多种实现。在JDK1.5中基本一样。
但是需要主意的是float和double最后面多一个delta的值。
4.assertNotNull/Null([String message,]Object obj);
判读一个对象是否非空(非空)。
5.assertSame/NotSame([String message,]Object expected,Object actual);
判断两个对象是否指向同一个对象。看内存地址。
6.failNotSame/failNotEquals(String message, Object expected, Object actual)
当不指向同一个内存地址或者不相等的时候,输出错误信息。
注意信息是必须的,而且这个输出是格式化过的。






以上内容为转,部分修改或者省略~
原作:Andy Schneider Richard Dallaway 等
编译:PMT 测试工作组

Leave a Comment.