- 浏览: 148145 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
415421979:
我也遇到了这个问题 求解啊
JBoss/Tomcat 安装路径带空格时 JNDI 无法初始化的BUG -
ivonxiao:
谢谢楼主的分享
异常管理系统 -
ivonxiao:
谢谢楼主的分享~~
Java对象的强、软、弱和虚引用
经验一、不要在测试用例的构造函数中做初始化
当我们需要增加一个测试时,我们要书写一个自己的测试用例,比如sometest。如果你喜欢在sometest的
构造函数中做有关的初始化工作,这可不是个好习惯。如下例:
public class sometest extends testcase{
public sometest(string testname){
super(testname);
//初始化代码
}
}
一旦初始化代码产生异常,比如illegalstateexception,junit随之将产生一个assertionfailederror,
并显示类似下面的出错信息:
junit . framework . assertionfailederror : cannotinstantiatetestcase : test1at
junit . framework . assert . fail ( assert . java : 143 ) at
junit . framework . testsuite$1 . runtest ( testsuite . java : 178 ) at
junit . framework . testcase . runbare ( testcase . java : 129 ) at
junit . framework . testresult$1 . protect ( testresult .java : 100 ) at
junit . framework . testresult . runprotected ( testresult. java: 117 ) at
junit . framework . testresult . run ( testresult. java : 103 ) at
junit . framework . testcase . run( testcase . java: 120 ) at
junit . framework . testsuite . run( testsuite . java , compiledcode ) at
junit . ui . testrunner$12 . run (testrunner. java : 429 )
这一大堆出错信息只会让人一头雾水,我们只知道junit无法实例化某个测试用例,到底出了什么问题,在
哪儿出错了呢?不知道!
那么好的做法是怎样呢?
答案是重载测试用例的setup()方法进行初始化。当setup()中的初始化代码产生异常时我们得到的
是类似下面的出错信息:
java . lang . illegalstateexception : oopsatbp . dtc . setup ( dtc .java: 34 ) at
junit . framework . testcase . runbare ( testcase .java: 127 ) at
junit . framework . testresult$ 1 . protect(testresult . java : 100 ) at
junit . framework . testresult . runprotected ( testresult . java: 117 ) at
junit . framework . testresult . run ( testresult .java : 103 )
...
显然这要清楚得多我们一下子就可以知道是在dtc.java 的第34 行产生了illegalstateexception
经验二、不要假定测试用例中测试的执行次序
我们知道在一个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 的执行
次序是不可预测的。
好的习惯是保持测试之间的独立性,使得它们在任何次序下执行的结果都是相同的。如果真得需要某些测试
按照特定的次序执行,我们可以借助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 中定义的父类的环境被初
始化了。当然这也有例外,就是基类可以处理任意的测试数据。
经验五、不要硬性规定数据文件的路径
我们经常需要从文件系统中读取测试数据,看下面的代码:
public void setup () {
fileinputstream inp ("c:\\testdata\\dataset1.dat");
...
}
这段代码需要把测试数据文件dataset1.dat 放在c:\testdata,这是有问题的。
第一,c 盘可能没有磁盘空间了测试人员不得不把数据文件放到其他路径;
第二,可能需要在其他操作系统比如linux 上执行这一测试。
所以,一个较好的替代方案是
public void setup () {
fileinputstream inp ("dataset1.dat");
...
}
但事实上这样仍不是很好,因为这要求数据文件的路径和测试执行的路径必须是同一个,如果几个不同
的测试都这样的话,那要把这些测试集合起来执行就有些困难,我们不得不频繁的改变当前路径。
为了解决这个问题,我们可以使用class.getresource()或者class.getresourceasstream(),这样我
们可以把数据文件放在这个class 的某个相对路径上。
数据文件应该尽可能和源代码一起都放在配置管理系统上,但这样一来如果我们采用上面的resource 机
制,我们就需要做一件工作,就是把数据文件从原来的位置-就是源代码的某个相对路径,拷贝到编译后
的位置,也就是class 文件的相应的相对路径。这其实并不复杂,因为从class 的package 就可以映射到
java文件的所在路径对于linux或者windows我们所要做的就是把package中的. 用file.separatorchar 替代。
经验六、把测试的代码和被测的代码放在同样的目录下
当我们把测试代码和被测的代码放在同一目录下时,我们就可以在编译被测代码的同时编译测试代码,从
而确保两者是同步更新的。事实上当前的普遍做法,就是把单元测试视为build 的一个环节。
经验七、正确命名测试
把测试用例命名为testclassundertest,比如如果被测的class 是messagelog,那么测试用例就叫
testmessagelog,这样做使得测试用例和被测的class一一对应,而在测试用例中每个测试的method 就
可以命名为
testloggingemptymessage()
testloggingnullmessage()
testloggingwarningmessage()
testloggingerrormessage()
同样是为了说清楚测试的是什么。正确的命名可以帮助测试代码的阅读者了解每个测试的目的。
经验八、书写测试时要考虑地区和国家设置
比如某个测试要使用日期,下面的代码就是创建日期对象的一种方法
Date date = DateFormat.getInstance ().parse ("dd/mm/yyyy");
但是如果运行上面测试代码的机器采用不同的地区国家设置,那么就会有问题。因此我们最好用下面的另
一种方法:
Calendar cal = Calendar.getInstance ();
Cal.set (yyyy, mm-1, dd);
Date date = Calendar.getTime ();
显然,第二种方法能够适应地区国家设置的变化。
经验九、利用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方法,干净利索如下例
assertEquals ("some message", result, expected, delta);
另外要一提的是:
assertSame()用来测试两个引用是否指向同一个对象
assertEquals()用来测试两个对象是否相等
经验十一、确保测试代码与时间无关
尽量避免可能过期的测试数据,这种数据应该可以手工或者自动的刷新。另外还有一个技巧就是在使用这些
数据前更改系统的当前日期,数据操作结束后再恢复日期。当然,使用这一技巧要注意可能的副作用。
经验十二、使用文档生成器做测试文档
我们当然可以使用文本编辑器来书写单元测试的文档,但是更好的方法是使用文档生成器比如JavaDoc自
动生成,这样我们就不需担心实现和文档之间的同步问题。自动生成的文档格式统一错误也少。
当我们需要增加一个测试时,我们要书写一个自己的测试用例,比如sometest。如果你喜欢在sometest的
构造函数中做有关的初始化工作,这可不是个好习惯。如下例:
public class sometest extends testcase{
public sometest(string testname){
super(testname);
//初始化代码
}
}
一旦初始化代码产生异常,比如illegalstateexception,junit随之将产生一个assertionfailederror,
并显示类似下面的出错信息:
junit . framework . assertionfailederror : cannotinstantiatetestcase : test1at
junit . framework . assert . fail ( assert . java : 143 ) at
junit . framework . testsuite$1 . runtest ( testsuite . java : 178 ) at
junit . framework . testcase . runbare ( testcase . java : 129 ) at
junit . framework . testresult$1 . protect ( testresult .java : 100 ) at
junit . framework . testresult . runprotected ( testresult. java: 117 ) at
junit . framework . testresult . run ( testresult. java : 103 ) at
junit . framework . testcase . run( testcase . java: 120 ) at
junit . framework . testsuite . run( testsuite . java , compiledcode ) at
junit . ui . testrunner$12 . run (testrunner. java : 429 )
这一大堆出错信息只会让人一头雾水,我们只知道junit无法实例化某个测试用例,到底出了什么问题,在
哪儿出错了呢?不知道!
那么好的做法是怎样呢?
答案是重载测试用例的setup()方法进行初始化。当setup()中的初始化代码产生异常时我们得到的
是类似下面的出错信息:
java . lang . illegalstateexception : oopsatbp . dtc . setup ( dtc .java: 34 ) at
junit . framework . testcase . runbare ( testcase .java: 127 ) at
junit . framework . testresult$ 1 . protect(testresult . java : 100 ) at
junit . framework . testresult . runprotected ( testresult . java: 117 ) at
junit . framework . testresult . run ( testresult .java : 103 )
...
显然这要清楚得多我们一下子就可以知道是在dtc.java 的第34 行产生了illegalstateexception
经验二、不要假定测试用例中测试的执行次序
我们知道在一个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 的执行
次序是不可预测的。
好的习惯是保持测试之间的独立性,使得它们在任何次序下执行的结果都是相同的。如果真得需要某些测试
按照特定的次序执行,我们可以借助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 中定义的父类的环境被初
始化了。当然这也有例外,就是基类可以处理任意的测试数据。
经验五、不要硬性规定数据文件的路径
我们经常需要从文件系统中读取测试数据,看下面的代码:
public void setup () {
fileinputstream inp ("c:\\testdata\\dataset1.dat");
...
}
这段代码需要把测试数据文件dataset1.dat 放在c:\testdata,这是有问题的。
第一,c 盘可能没有磁盘空间了测试人员不得不把数据文件放到其他路径;
第二,可能需要在其他操作系统比如linux 上执行这一测试。
所以,一个较好的替代方案是
public void setup () {
fileinputstream inp ("dataset1.dat");
...
}
但事实上这样仍不是很好,因为这要求数据文件的路径和测试执行的路径必须是同一个,如果几个不同
的测试都这样的话,那要把这些测试集合起来执行就有些困难,我们不得不频繁的改变当前路径。
为了解决这个问题,我们可以使用class.getresource()或者class.getresourceasstream(),这样我
们可以把数据文件放在这个class 的某个相对路径上。
数据文件应该尽可能和源代码一起都放在配置管理系统上,但这样一来如果我们采用上面的resource 机
制,我们就需要做一件工作,就是把数据文件从原来的位置-就是源代码的某个相对路径,拷贝到编译后
的位置,也就是class 文件的相应的相对路径。这其实并不复杂,因为从class 的package 就可以映射到
java文件的所在路径对于linux或者windows我们所要做的就是把package中的. 用file.separatorchar 替代。
经验六、把测试的代码和被测的代码放在同样的目录下
当我们把测试代码和被测的代码放在同一目录下时,我们就可以在编译被测代码的同时编译测试代码,从
而确保两者是同步更新的。事实上当前的普遍做法,就是把单元测试视为build 的一个环节。
经验七、正确命名测试
把测试用例命名为testclassundertest,比如如果被测的class 是messagelog,那么测试用例就叫
testmessagelog,这样做使得测试用例和被测的class一一对应,而在测试用例中每个测试的method 就
可以命名为
testloggingemptymessage()
testloggingnullmessage()
testloggingwarningmessage()
testloggingerrormessage()
同样是为了说清楚测试的是什么。正确的命名可以帮助测试代码的阅读者了解每个测试的目的。
经验八、书写测试时要考虑地区和国家设置
比如某个测试要使用日期,下面的代码就是创建日期对象的一种方法
Date date = DateFormat.getInstance ().parse ("dd/mm/yyyy");
但是如果运行上面测试代码的机器采用不同的地区国家设置,那么就会有问题。因此我们最好用下面的另
一种方法:
Calendar cal = Calendar.getInstance ();
Cal.set (yyyy, mm-1, dd);
Date date = Calendar.getTime ();
显然,第二种方法能够适应地区国家设置的变化。
经验九、利用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方法,干净利索如下例
assertEquals ("some message", result, expected, delta);
另外要一提的是:
assertSame()用来测试两个引用是否指向同一个对象
assertEquals()用来测试两个对象是否相等
经验十一、确保测试代码与时间无关
尽量避免可能过期的测试数据,这种数据应该可以手工或者自动的刷新。另外还有一个技巧就是在使用这些
数据前更改系统的当前日期,数据操作结束后再恢复日期。当然,使用这一技巧要注意可能的副作用。
经验十二、使用文档生成器做测试文档
我们当然可以使用文本编辑器来书写单元测试的文档,但是更好的方法是使用文档生成器比如JavaDoc自
动生成,这样我们就不需担心实现和文档之间的同步问题。自动生成的文档格式统一错误也少。
发表评论
-
Maven 2.0:编译、测试、部署、运行
2008-01-24 16:55 1313摘要:Maven1.0已经历了几年的时间,并且作为Ant的替代 ... -
使用Jetty和DWR创建伸缩性Comet程序
2008-01-24 16:03 2374异步服务器端事件驱动 ... -
使用MOCK对象进行单元测试
2008-01-24 15:50 11501.出了什么问题? 单元测试的目标是一次只验证一个 ... -
JUnit常用断言方法
2008-01-24 15:35 1178常用的方法如下: assertEquals(a, b) ... -
Java应用利器组合:Ant+JUnit+Cobertura
2008-01-24 15:31 1181看标题就知道,这个是开发一个Java应用的利器组合,使 ... -
J2EE架构的6个最佳实践
2008-01-24 14:39 1155虽然许多文章曾经讨论过J2EE最佳实践。那么,为什么我还要再写 ... -
开发完整J2EE解决方案的八个步骤6
2008-01-24 13:59 829VII、组合和配置 组 ... -
开发完整J2EE解决方案的八个步骤5
2008-01-24 13:55 896IV、对象设计 在体系规范的指导下,设计可在技术上扩展和适 ... -
开发完整J2EE解决方案的八个步骤4
2008-01-24 13:53 1002应用体系 应用体系 ... -
开发完整J2EE解决方案的八个步骤3
2008-01-24 13:51 787III、体系规范 经过前面的两个步骤,商业领域的问题和需求 ... -
开发完整J2EE解决方案的八个步骤2
2008-01-24 13:49 808II、面向对象的分析 分析产生问题域模型:类、对象和交互。 ... -
开发完整J2EE解决方案的八个步骤1
2008-01-24 13:47 1197摘要 Java 2企业 ... -
单元测试策略
2008-01-24 13:27 1316本文为作者在使用Junit ... -
junit基本教程
2008-01-24 13:06 1715Eclipse中配置junit 在要使用JUNIT的 ... -
junit教程
2008-01-24 12:50 4977您是怎样编写测试代码的呢? 在调试器中使用表达式也许是最简单 ... -
junit单元测试的意义
2008-01-24 12:29 2837为什么要进行单测试. 1. ... -
HttpServletRequest对象getParameter()方法在各web容器中返回值问题
2008-01-24 10:04 3062Servlet中HttpServletRequest对象的ge ... -
JBoss/Tomcat 安装路径带空格时 JNDI 无法初始化的BUG
2008-01-08 17:55 2046JBoss/Tomcat 安装路径带空格时 JNDI 无法初始 ... -
J2EE项目异常处理
2008-01-05 17:34 913J2EE项目异常处理 ... -
jndi的命名
2008-01-05 11:26 1056jndi是一种通过名字获取对象的一种技术,一般在java中 ...
相关推荐
JUnit是Java编程语言中最常用的单元测试框架之一,它允许开发者编写可执行的测试用例来验证代码的功能。...无论是新手还是经验丰富的开发者,深入掌握JUnit都是提高开发效率和代码质量的必要步骤。
总结,使用JUnitTest在Android开发中进行单元测试是提升代码质量和可维护性的关键步骤。通过创建测试用例、运行测试、分析测试结果,开发者能够更好地理解和改进代码,确保应用的稳定性和可靠性。JUnitTestDemo提供...
13. **学习笔记**:个人的学习笔记可能包含了作者在实践过程中遇到的问题、解决方案和经验总结,对于学习者来说是一份宝贵的实战经验。 以上只是部分可能涵盖的知识点,实际的压缩包文件可能还包含更多细节和深入的...
JUnit是Java编程语言中最常用的单元测试框架之一,它为开发者提供了编写和运行可重复的、自动化的测试用例的能力。...无论是初学者还是经验丰富的开发者,理解并运用JUnit都是提高开发效率的关键步骤。
总结,JUnit5通过引入许多新特性极大地提高了测试的灵活性和效率,同时也考虑到了与旧版本的兼容性问题。无论是对于新手还是经验丰富的开发人员来说,它都是一个值得深入学习和使用的强大工具。
总结起来,"junit_1.3.jar.zip"这个压缩包包含了JUnit 1.3版本的核心库,它是进行Java单元测试的重要工具。虽然当前的JUnit已经发展到了更高级的版本,但理解早期版本的机制有助于我们更好地掌握单元测试的理念和...
JUnit是Java编程语言中最常用的单元测试框架之一,用于编写和运行可重复的自动化测试用例。这个"Junit-jar包"显然...无论你是新手还是经验丰富的开发者,理解并熟练使用JUnit都是提升开发效率和代码质量的关键步骤。
《Junit:Java单元测试的重要工具》 Junit,作为Java开发者耳熟能详的名字,是Java编程领域中最广泛使用的单元测试框架。...无论你是初学者还是经验丰富的开发者,深入理解和使用Junit都将对你的编程生涯大有裨益。
JUnit 4.12是Java开发领域中广泛使用的单元测试框架的一个重要版本。这个轻量级的工具使得开发者能够编写可重复执行的...无论是初学者还是经验丰富的开发者,都应该熟练掌握JUnit 4.12的使用,以提升自己的开发实践。
在实验总结中,报告总结了Junit单元测试的结果,包括测试的结论、测试的建议和测试的改进建议等。 本文档是关于Junit单元测试的详细报告,报告涵盖了Junit单元测试的所有方面,包括实验目的、实验环境、实验内容、...
根据提供的信息,我们可以总结出以下关于《JUnit实战(第2版)》的重要知识点: ### 1. JUnit简介 - **定义**:JUnit是一个广泛使用的Java单元测试框架,旨在简化测试过程并提高软件质量。 - **版本更新**:本书...
总结起来,JUnitTest是Java开发中不可或缺的一部分,它提供了一种标准化的方式来编写、组织和执行测试用例,确保代码的可靠性和稳定性。无论你是新手还是经验丰富的开发者,熟练掌握JUnitTest都将极大地提升你的工作...
### JUnit与Eclipse:详解JUnit4.x在Eclipse中的使用 #### 一、前言 JUnit 是一种常用的Java单元测试框架,可以帮助开发者确保代码的质量和稳定性。本教程旨在为有一定经验的Java开发者提供如何在Eclipse环境中...
总结,这份"PPT讲义"全面覆盖了JUnit 4的关键特性和实践,无论是初学者还是有经验的开发者,都能从中受益,提升单元测试的能力,从而提高代码质量,减少潜在的缺陷。通过深入学习和实践,我们可以更好地利用JUnit 4...
总结起来,Junit 4.12以其强大的功能和对Spring框架的良好支持,成为Java开发者进行单元测试的首选工具。通过深入理解和熟练运用其特性,可以极大地提升软件的质量和开发效率。无论是对于初学者还是经验丰富的开发者...
总结起来,这个压缩包提供的是JUnit的两个关键版本,对于理解测试框架的历史发展和Java单元测试的基本概念非常有帮助。无论你是初学者还是经验丰富的开发者,研究这两个版本之间的差异和改进都能加深对测试驱动开发...