论坛首页 综合技术论坛

对junit的一点体会

浏览 44982 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2005-03-18  
muziq 写道
CafeBabe 写道
用一个jdbc工具插入所有的测试数据"

More detail please.

晕,这又不难。
我是所有的初始化sql放在文件中,然后写一个类比如说JdbcUtils去读这个文件,按顺序执行每一条sql
代码类似这样
public void setUp();{
  ApplicationContext ac=...;
  JdbcUtils jdbc=(JdbcUtils);ac.getBean("jdbcUtils");;
  jdbc.execute("init.sql");;
}


init.sql类似这样:
insert into tbl_user
(id, name);
values
(seq_user.nextval,'abc');;
//...
0 请登录后投票
   发表时间:2005-03-18  
验证数据库操作的正确性,有什么好的办法?
0 请登录后投票
   发表时间:2005-03-18  
muziq 写道
CafeBabe 写道
用一个jdbc工具插入所有的测试数据"

More detail please.

他就是重新清空数据库数据,然后再全部载入数据啦。

这样估计不太行的哦,不知道一个全程测试下来,时间要多少。
0 请登录后投票
   发表时间:2005-03-19  
jinfeng_Wang 写道
muziq 写道
CafeBabe 写道
用一个jdbc工具插入所有的测试数据"

More detail please.

他就是重新清空数据库数据,然后再全部载入数据啦。

这样估计不太行的哦,不知道一个全程测试下来,时间要多少。

你也可以不让hibernate drop所有的tabel和sequence,而完全通过init.sql来控制,你还可以有多个init.sql,不同的testcase甚至test方法对应不同的初始化脚本,这样可以减少不必要的清除,但带来的麻烦是你要维护很多个脚本。

你不会每次都运行全部的testcase吧?大多数时候只需要运行一个或若干个testcase中的某些test方法,只有在你做了某些牵涉范围较大的重构时,才需要运行全部,当然你去吃中饭或者下班的时候可以运行全部testcase,等你吃完饭或第二天就能看到结果了

校验也可以通过这个JdbcUtils来做
public class JdbcUtils{
  public Object[] queryOneRecord(String sql);{
    //...
  }
}

public class AssertionUtils{
  public static void assertEquals(Object[] expected,Object[] array);{
    //..
  }
}

Long userId=userDao.create(user);;
AssertionUtils.assertEquals(
new Object[]{user.getId();,user.getName();},
jdbc.queryOneRecord("select id,name from tbl_user where id="+userId););;
0 请登录后投票
   发表时间:2005-03-19  
CafeBabe 写道

你不会每次都运行全部的testcase吧?大多数时候只需要运行一个或若干个testcase中的某些test方法,只有在你做了某些牵涉范围较大的重构时,才需要运行全部,当然你去吃中饭或者下班的时候可以运行全部testcase,等你吃完饭或第二天就能看到结果了

晕,当然是频繁地运行所有测试乐!
0 请登录后投票
   发表时间:2005-03-19  
swing 写道
CafeBabe 写道

你不会每次都运行全部的testcase吧?大多数时候只需要运行一个或若干个testcase中的某些test方法,只有在你做了某些牵涉范围较大的重构时,才需要运行全部,当然你去吃中饭或者下班的时候可以运行全部testcase,等你吃完饭或第二天就能看到结果了

晕,当然是频繁地运行所有测试乐!

对,以前我一天只能全部运行个4,5次,一方面可能是因为我每次都用hibernate重建所有的表,只有一个init.sql文件,里面包含了所有的初始化数据,还有就是测试时用的是远程的oracle数据库。优化一下应该可以提高速度,但要频繁地运行所有测试不知道能不能做到
那你是怎么测试的?
0 请登录后投票
   发表时间:2005-03-19  
有个比较慢的自动测试,总比没有自动测试要好。
0 请登录后投票
   发表时间:2005-03-20  
CafeBabe 写道
swing 写道
CafeBabe 写道

你不会每次都运行全部的testcase吧?大多数时候只需要运行一个或若干个testcase中的某些test方法,只有在你做了某些牵涉范围较大的重构时,才需要运行全部,当然你去吃中饭或者下班的时候可以运行全部testcase,等你吃完饭或第二天就能看到结果了

晕,当然是频繁地运行所有测试乐!

对,以前我一天只能全部运行个4,5次,一方面可能是因为我每次都用hibernate重建所有的表,只有一个init.sql文件,里面包含了所有的初始化数据,还有就是测试时用的是远程的oracle数据库。优化一下应该可以提高速度,但要频繁地运行所有测试不知道能不能做到
那你是怎么测试的?


我的逻辑是这样的:
1、我想进行TDD
2、TDD的过程必须频繁地运行所有测试
3、我需要一套可以频繁运行的测试用例
4、要能够频繁地运行所有测试,那么对于每个单元测试必须满足两个条件:
*******1)能够快速执行
*******2)运行这个用例的环境必须足够简单,我对这个简单的理解是,运行这个用例只需要足够的jar包支持即可。

5、一个单元测试要快速执行,需要控制两个方面:测试环境搭建和测试用例(单个test方法)。
6、要想测试环境搭建快速,则需要尽量少用(最好是不用)外部资源,主要是:搭建真实的数据库环境提供测试数据,搭建真实的容器供测试用例运行。(文件资源通常可以接受,当然一般也需要控制)
7、要想测试用例运行快速,主要是控制assert的代价,比如对xml类型的assert,对复杂对象的assert,可能会导致速度过慢,但是一般情况下测试用例的运行速度都是可以接受的,一旦出现难以接受的慢速度,通常说明设计(或者代码)有问题,需要重构。
8、要运行用例的环境必须足够简单,需要用例不依赖外部环境,这里最明显的依赖是真实的数据库环境和容器(主要是servlet和jsp,如果是对EJB的测试,还牵涉EJB容器)。
9、要用例不依赖外部环境,则目标单元需要不依赖外部环境。
10、我要进行的是TDD,不是测试!因此,这里有一个很重要的原则:足够简单的代码不特地为它编写单元测试。
11、到这里,答案已经很显然,按照第10条所说的原则,在设计中,凡是必须牵涉外部资源的代码(如servlet、jsp、dao等等)必须足够简单,这样我就可以不对它进行测试。
12、要使必须牵涉外部资源的代码足够简单,那么我们需要按一些基本原则去设计它们(实际上这样做是促进乐我们遵循面向对象设计的基本原则):
******0)为了方便讨论,我将称必须牵涉外部资源的代码为A类代码,而除此以外那些不牵涉外部资源的代码,或者说我们需要对它们进行单元测试的代码,我称为B类代码。
******1)为A类代码定义非常单一的职责,越是简单的职责,能够使我们获得越简单的代码
******2)让A类代码依赖B类代码,在设计B类代码时,需要遵循依赖倒置的原则,以促使B类代码完全不会依赖A类代码。

13、这个逻辑接着下去,可能就是:凡是导致必须牵涉外部资源的代码变复杂的技术我都考虑进行改进或者不使用;或者换一种说法,需要构建一个能够让必须牵涉外部资源的代码总是非常简单的架构。
14、到这里,请一定注意第一点,它是整个逻辑的起点,没有它,我可能完全不会这么做!
15、仍然会有些特殊情况,需要对必须牵涉外部资源的代码进行测试,但是这个时候这样的代码已经是相对少量的,我使用mock objects,虽然使用它构建的测试用例可能会显得代码多而复杂,但是在速度和所需的运行环境这两个关键点上令人满意,因此最终我采用乐它。
16、是不是频繁地运行所有测试,可能主要是牵涉你编写测试的目的(象我,是为乐TDD),虽然存在很多不同的目的,不过,我想主要还是用于检验开发代码的质量的,这个时候,测试运行的频率越高,它的价值就越大;所以无论测试代码如何,高频率地执行测试是非常必要的。
17、集成测试可能其运行的代价确实都比较昂贵,我上面的说法不代表我忽视它们或者认为这样的测试不合理。
0 请登录后投票
   发表时间:2005-03-21  
swing的第11条是重点!

DAO做到足够简单的话,也就不必单独测试。而且,从架构的角度考虑,DAO接口也必须是对实体进行简单的CRUD操作。这一点说起来简单,在实际编码的时候确很容易将业务逻辑搅和进来,这样在降低系统可维护性的同时,也增加的测试的难度。参见http://www.iteye.com/viewtopic.php?t=11474
1 请登录后投票
   发表时间:2005-03-21  
swing 写道

10、我要进行的是TDD,不是测试!因此,这里有一个很重要的原则:足够简单的代码不特地为它编写单元测试。
11、到这里,答案已经很显然,按照第10条所说的原则,在设计中,凡是必须牵涉外部资源的代码(如servlet、jsp、dao等等)必须足够简单,这样我就可以不对它进行测试。

你好像是这个意思:
1 dao牵涉到外部资源
2 dao可以做到足够简单
所以dao就不用测试了
什么叫做“dao足够简单“?好像spring dudu也说过,你如果用spring,hibernate,那你的dao代码可能就很“简单”,比如
public void saveUser(User user);{
  getHibernateTemplate();.save(user);;
}

这个方法里只有一行代码,所以“简单”,“一般“情况下不会有问题,除非你那天头晕,把save(user)写成了delete(user)
但仔细想想,要是你的mapping文件写错了,你即使写了save,它又能工作吗?所以我们测试hibernate dao,不仅是测试代码,也是测试映射文件。看似简单的代码其实不简单,hibernate这样的orm tool其实把很多本应该写在代码中东西挪到了配置文件里面。
再说了,不是所有的方法都能够写得如此“简单”的,比如说我们的项目中经常有这种东东,Parent<-->Child一对多,需要这样一个方法,
public void update(Parent p){
}
这个方法要update parent,同时对它的children做相应的insert,update或者delete
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics