一个通用的单元测试框架的思考和设计

上传人:wt****50 文档编号:33962383 上传时间:2018-02-19 格式:DOC 页数:14 大小:1.47MB
返回 下载 相关 举报
一个通用的单元测试框架的思考和设计_第1页
第1页 / 共14页
一个通用的单元测试框架的思考和设计_第2页
第2页 / 共14页
一个通用的单元测试框架的思考和设计_第3页
第3页 / 共14页
一个通用的单元测试框架的思考和设计_第4页
第4页 / 共14页
一个通用的单元测试框架的思考和设计_第5页
第5页 / 共14页
点击查看更多>>
资源描述

《一个通用的单元测试框架的思考和设计》由会员分享,可在线阅读,更多相关《一个通用的单元测试框架的思考和设计(14页珍藏版)》请在金锄头文库上搜索。

1、一个通用的单元测试框架的思考和设计01-思考篇发布时间: 2011-8-02 13:08 作者: CrazyCoder2010 来源: 51Testing 软件测试网采编 字体: 小 中 大 | 上一篇 下一篇 | 打印 | 我要投稿 | 推荐标签: 软件测试 单元测试1. 先从问题说起写过程序的同学都知道,做好单元测试提高代码覆盖率对整个项目意味着什么,但是做好单元测试并不是一件那么简单的事情,因为实际业务逻辑和运行环境的复杂性,导致了我们的单元测试代码不可能都像那些 helloWord 那么简单,比如现在的业务系统绝大多数都是基于数据库的,怎么做单元测试才能做到每次做单元测试时都是一个干净

2、的测试环境-即上次单元测试的数据库操作不会影响本次测试的结果(比如一个 createUser 操作,第一次单元测试运行成功了,但是第二次运行却失败了,因为代码里做了重名判断) ,还有 web 层的单元测试如何进行,web 框架如何启动,那些万恶的 httpServletRequest,HttpSession 等接口,头大。 。 。2. 现有的框架及对比目前有很多的开源测试框架,一下列举几个最常用的junit 这个地球人都知道,单元测试的先祖框架,核心,掌握他并熟练运用那是必须滴testNG,号称下一代单元测试框架,火了一阵子,功能比 junit 更强大,但是依旧无法撼动 junit 的王者地位

3、dbunit,基于数据库的测试框架,提供了可以通过 xml 格式来准备数据的方案,使测试数据和真实的数据库数据分离开,测试者可以针对自己在文件中造的数据进行程序的断言,也提供了一个与 junit 集成的基类 DBTest,这个基类封装了一些 dbunit 启动的操作,把一些通用复杂的操作对操作者透明,但是这也是一个劣势,就是一旦继承了这个基类,你就无法继承自己的类(都是 java 单继承惹的祸)SpringTest 框架,spring2。5以后提供了一个 test 框架,提供了大量的基类,测试框架会自动启动 spring 容器,把 spring 中的 bean 自动注入进来,另外还提供了可以对

4、测试方法进行事务控制,每个测试方法测试完成后通过框架控制自动回滚的功能,优势很明显,充分发挥了 spring 框架的优势,对开发者屏蔽细节,自动事务控制,缺点也很明显,测试必须依赖于 spring 框架,对于那些没用到 spring 框架的项目来说只能望洋兴叹了Struts2Test,struts2提供的单元测试用例基类,提供对 httprequest,response,session 等对象 mock(基于 springtest 框架) ,可以初始化 struts 框架,这对基于 struts2的应用系统来说是个福音,不幸的是要用这个框架,必须依赖 spring 框架,否则一切玩完3. 框架

5、设计的目标核心的框架都在上面了,不难看出,在这几个主流框架的使用中,spring 框架在其中扮演了很重要的角色,如果项目中没有用到 spring,有些测试框架的支持功能根本无法使用!如何让各个框架可以很容易的整合起来又能发挥自身最大的优势呢?在进行具体的设计之前,我们来展望一下我们期望的测试流程是怎么样的(图) 测试开始前记录数据库状态是1,开始测试后把属于某个测试用例的准备数据加载到数据库中,这时候数据库的状态已经变成了2,接着运行具体的测试用例,测试方法中有对数据库的操作,因此变成了状态3,我们希望对测试的方法进行事务控制,这样在该方法内做的所有数据库操作都可以在测试完成后被会被回滚到先前

6、状态,因此测试方法执行完后,状态又变回了2,当该测试用例的测试方法都执行完毕后,框架负责把先前插入的准备数据删除,这样数据库状态又回到了原始的状态1,这样的优势非常明显,无论这个测试用例执行多少次,用例执行完毕后测试后都会回到原始状态,不会对现有数据造成污染又能保证每次执行都用相同的数据,何乐不为?刚刚谈了理想,接下来看一下怎样的一个框架才能满足我们的需求1)不需要和任何框架耦合在一起这点很重要,整个框架应该围绕一个基本测试框架展看如 testng 或 junit 而不是 spring 这种重量级的框架(相对 junit 来说 spring已经是很重量级的东东了)2)可以很容易为框架添加新的特

7、性,但是不需要改动框架本身的代码-对于 springtest 或 dbunit 等框架,相对于我们的测试框架只是一些功能上的 enhancement,可以通过功能扩展加到框架中,而不是通过继承他们提供基类的方式来直接依赖他们3)准备测试数据做基于 db 的单元测试的人都有感触,单元测试很大一部分时间都在准备数据,因此框架应该支持让使用者通过更加便利的方式去准备数据如常用的 excel 文件或 xml 文件或其他 csv 格式框架使用者不需要去手动的加载这些数据准备文件,框架需要提供一种契约,如文件名和类名名称路径保持一致,框架自动为当前测试类加载对应的数据,框架使用者只需要书写测试代码,把测试

8、数据放到指定文件夹下即可4)事务控制这个没什么捷径,只能靠 jdbc 的 api 来实现。一个通用的单元测试框架的思考和设计02-设计篇发布时间: 2011-8-03 10:59 作者: CrazyCoder2010 来源: 51Testing 软件测试网采编 字体: 小 中 大 | 上一篇 下一篇 | 打印 | 我要投稿 | 推荐标签: 软件测试 单元测试第一节里介绍了我们框架设计的目标,这篇主要介绍的是这个框架主要的设计思路和关键技术点 1. 如何扩展 junit 的功能,使 junit 在启动时可以做一些我们定制化的功能?junit4建立了以 Runner 为核心的测试框架运行机制,在

9、junit3的版本中,我们知道要运行一个 junit 测试用例,必须继承一个 TestCase 基类,junit4 则不需要这个限制,只需要标注一下要运行测试的方法为Test 就可以了,怎么做到的呢?就是这个 Runner 机制,这里不介绍 Junit4的运行机制,可以从 org。 junit。runner 。BlockJUnit4ClassRunner 中得到答案,像 springtest 框架也是扩展了这个类的功能来达到扩展目的的2. 如何让 junit4框架提供更多的自定义注解的功能?junit4提供了诸如Test,BeforeClass ,Before 等注解来简化单元测试过程,在我们

10、这个通用框架的设计中,我们系统提供更多自己定制的注解来扩展 junit 的功能,如我们希望提供一个DataSet 注解,当测试类有此注解时,框架自动解释这个注解,并把当前类同级目录下加载与类名相同的 xsl 文件,该文件里存放的是该单元测试类的准备数据,这样就能解决上一节中提到的测试文件和测试类之间约束的目的,开发只需要关注准备数据和写测试类,其他的事情都交给框架去搞吧,通过跟踪 Junit 的源码我们不难看出单元测试类的执行要经过 ObjectcreateTest()方法(测试框架加载测试类)和 StatementmethodInvoker(FrameworkMethodmethod ,Ob

11、jecttest) (执行测试方法) ,这样我们就可以通过扩展 BlockJUnit4ClassRunner 类通过覆写这两个方法,让其支持我们更多的功能特性3. 回顾一个 测试用例的测试过程一个测试用例的执行大约可以包含这样几个步骤,在创建测试实例后,测试方法前,测试方法执行后,测试方法抛出异常后,因此我们可以根据这些功能定义一个统一接口 IUnitTestExecuteListener,接口里定义这4个方法prepareTestInstance-创建测试实例后beforeTest-测试方法前afterTest-测试方法执行后afterThrowable-测试方法抛出异常后这样对于不同的功能

12、扩展,我们只需要提供相应的子类即可,如我们前面提到的那个DataSet 注解的方式来加载测试数据准备文件,就可以提供一个 ExcelDataProviderListener 类,只要在其 prepareTestInstance 方法里把测试文件内容读出来,插入到数据库中即可-soeasy!,对于要进行事务控制的测试方法Transactional 标签,我们也可以提供一个实现类来实现事务控制的目的- 这样对于框架而言,新功能的扩展只需要添加对应的子类即可,体现了软件设计的开- 闭原则4. 框架执行流程图解释:IUnit 是我们为这个通用框架 YY 的名字:)从这张流程图上可以看出,IunitRu

13、nner 和 IUnitTestExecutionListener 是我们整个框架的核心,一个 Runner 有多个 Listener,当测试的生命周期开始后,runner 会循环调用已注册 listener 的 prepareTestInstance,beforeTest ,afterTest,afterThrowable 方法执行对应的功能5. 详细设计- 类图解释:整个框架最核心的类和接口只有三个 IunitRunner,这个是运行的切入点,用来注册每个测试类指定的 listener(通过寻找测试中上的IUnitTestExecuteListeners 标注) ,所有的功能扩展都是围绕

14、IUnitTestExecuteListener 展开,如类图中描述的 GuiceStrapupListener 用来启动 guice 容器,DataProviderListener 用来加载测试准备数据6. 千呼万唤始出来-最终的测试用例长什么样子对于最终使用框架的开发者而言,根据自身需要通过注解来动态加载所需要的 listener 即可(可以指定多个) ,注意测试用例上要加个RunWith 标注,指定要执行的 runner 为 IunitRunner 这样 junit 框架才能用我们提供的 runner 来运行,实际使用的时候这些东东可以都放到一个测试父类中去完成,开发者只需要关注自身用到

15、的 listener 即可viewplaincopytoclipboardprint?packagecom.crazycoder2010.iunit;importstaticorg.hamcrest.MatcherAssert.assertThat;importstaticorg.hamcrest.Matchers.equalTo;importorg.junit.Test;importorg.junit.runner.RunWith;importcom.crazycoder2010.iunit.annotation.IUnitDataSet;importcom.crazycoder2010.i

16、unit.annotation.IUnitTestExecuteListeners;IUnitDataSet(dbunitFile=AppTest.xml)RunWith(IUnitRunner.class)IUnitTestExecuteListeners(TransactionalListener.class,DatasetProviderListener.class)publicclassAppTestextendsAbstractIUnitTestCaseTestpublicvoidtestHello()assertThat(hello,equalTo(hello);一个通用的单元测试框架的思考和设计03- 实现篇-核心类源码发布时间: 2011-8-04 10:37 作者: CrazyCoder2010 来源: 51Testing 软件测试网采编 字体: 小 中 大 | 上一篇 下一篇 | 打印

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 社会民生

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号