分享
 
 
 

与JUnit干杯 ---- JUnit框架的架构原理以及应用

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

DRINKING WITH JUNIT

作者: 乐晨光 [airwalker@263.net] (欢迎自由转载本文,但请注明作者及出处)

安全合理而富有可扩展性与可读性的测试代码进入了对象中,它就象一棵大数那样支撑起了整个工程。

1. PURPOSE

u 理解系统测试与单元测试的目的与方式

u 考察Junit测试框架的客户层应用;并架构一个待测试的系统案例。

u 考察分析Junit的框架架构原理。

2. THE TESTING

2.1 软件熵(software entropy)的概念:一个程序从设计很好的状态开始,随着新的功能不断地加入,程序逐渐地失去了原有的结构,最终变成了一团乱麻。(其实该处的“很好的状态”得加个?)

2.2 测试的目的:简单而极具活力,写出高质量的软件并解决软件熵这一问题。

2.3 测试的分类:白箱测试、黑箱测试;或,单元测试、集成测试、功能测试等有多种分类方法。

白箱测试 -> 指知道被测试的软件如何(how)完成功能测试和完成什么样的功能(what)的条件下所作的测试。(一般由开发人员完成)

单元测试应属于白箱测试。

黑箱测试 -> 在知道被测试的软件完成什么样(what)的功能的条件下所作的测试。(一般由测试人员完成)

单元测试 -> 目的为验证一个或若干个类是否按所设计那样正常工作与表现。

集成测试 -> 验证所有的类是否可以相互配合,协同完成特定的任务。(复杂的信号与事件通讯与状态机密集大的运作测试)

<<<< Junit应用于单元测试 >>>>

2.4 测试作为一项持续的过程,它贯穿与开发的整个过程中,单元测试尤适合迭代增量式(iteraton and incremental)的开发过程。

最简单的说:测试就是比较预期结果是否与实际执行结果一致。

3.ARCHITECTURE OF JUNIT

3.1 Goal of JUnit

u 创建一个通用的测试框架,将测试代码封装入对象中,从而使开发者乐于同步设计并配置自己的单元测试。

u 让测试代码具备保值性,使(以往是个人化的)测试代码的进行方式标准化,可为多人共同浏览、维护。

u 将测试代码从系统代码中剥离开,二者可同步发展。

3.2 JUnit的框架成员逻辑分析

1. 被测试的对象(类,多个类,子系统)(Object be Tested)

2. 对测试目标进行测试的方法与过程集合,可将其称为测试容器。(TestCase)

3. 测试事务的集合,可容纳多个测试容器(TestCase),将其称作测试事务包。(TestSuite)

4. 测试结果的描述与记录。(TestResult)

5. 每一个测试方法所发生的与预期不一致状况的描述,称其测试失败元素。(TestFailure)

6. JUnit Framework中的出错异常。(AssertionFailedError)

3.3 JUnit框架功能以及原理描述(junit.framework.*)

u Test接口与TestCase、TestSuite形成了Composite结构,Run(TestResult) 则是Composite Methode。Test为Component,派生出的TestCase为Leaf,是测试的执行元素;TestSuite为Composite,其可通过addTest(Test)来容纳Test组合(TestCase or TestSuite)形成测试包。

u TestCase可在框架中视为测试单元的运行实体。用户可以通过它派生自定义的测试过程与方式(单元),利用Command Pattern与Composite Pattern使其形成可组合装配的可扩展的测试批处理。TestCase本身的运作操作为run(TestResult),其中分别执行setUp(),runTest(),tearDown()来架构测试过程。Template Mothod Pattern使用户无须了解执行框架的过程细节,而只需重定义特性化的测试预处理,测试单元过程,以及测试完毕测试三个Template Mothod就能使测试正确工作。

u 用户层可通过Java的匿名内部类(Anonymous Inner Classes)来集成化重载runTest()形成特性测试类,同时JUnit3.0版本以后则支持利用Java的Class属性来动态框架后台生成这些特性测试单元类,而用户只需在TestCase派生类的testXXX()即可,在suite中使用return new TestSuite(MyTestCase.class);后该TestSuite就包含了所有testXXX为测试过程的TestCase类对象集合。

u Assert类包含了assertEqual(..),assertSame(..),assertTrue(.)等静态工具方法(static tools methods),为使用户对系统所了解的类型尽可能少,JUnit框架将Assert作为了TestCase的超类,TestCase同时继承了Assert的实现与Test接口(class Adepter pattern)。用户可在TestCase中直接调用这些assertXXX(..)等静态工具方法。

u TestResult描述了整个测试执行过程的测试结果,JUnit框架将其作为参数传递与Test的run(.)间,当测试任务执行完毕后,TestResult内则包含了所有TestCase的测试结果。框架默认的TestResult为TextTestResult,用户也可以自定义其TestResult的回显格式,譬如HTMLTestResult。

TestFailure描述了测试过程中的错误信息,TestResult通过Vector容纳了测试过程中生成的TestFailure,将其作为测试结果参数依据。

4. CLIIENT LAYER OF JUNIT

Import junit.framework.*;

用户通过派生TestCase来自定义特性Test案例,在TestCase中可包含系统待测试类型的对象,同时在其内定义若干testXXX()做test method。

覆盖setUp()来为每一次测试前做系统状态预处理,在tearDown()中清理。

安排测试过程有两种常用的方法:

1. 通过创建内部类来集成化覆盖runTest()方法,里边填充testXXX()

2. 通过class作为TestSuite的构造参数来动态创建测试包。( 其中所有的testXXX()均分别作为了一个新的特性TestCase的测试主方法[runTest{testXXX();}中] )

注意每一次测试(runTest)都应该相互是相互独立的,被测试对象不应该有上下文关系。(这是由于TestSuite容纳Test的vector的无序性)

5. TEST ZERG-COMMAND-SYSTEM WITH JUNIT

作为JUnit的测试案例,我架构了一个测试案例。

JUnit作为一个单元测试框架,开发者应该明确创设什么样的测试,如何测试,测试系统的什么部分以及方式,或是测试系统的整合表现。

该系统描述的是一个外星种族Zerg之星球作战指令系统。

ZCommand系统是一个Command & Composite架构,ZcommandGroup容纳若干命令(可视为批处理),ZconcreteCommand(ZCFire/ZCLoadAmmo/ZCAction)描述了3种具体命令类别(包含具体特性参数)

Zcommand的execute是一个composite method,可处理组合命令的批量执行。

架构这个系统的同时,要利用JUnit框架来测试该组合的性质。考察该命令系统,算法复杂区域表现在组合集成的过程里,以及执行组合执行的遍历过程。

public class TestCommandModel extends TestCase {}1. testCommandGroupCount() 测试一份组合命令所包含的子命令数目。

2. testCommandString() 测试组合命令执行的遍历回显过程。

3. testCommandGroupUpdate() 测试add, remove, clear等组合操作的正确性。

(详见junitzerg.test.TestCommandModel.java)

ZfighterMachine描述了一架作战指挥终端。ZergCommandCentre描述了Zerg作战指挥处理中心,ZfighterMachine将作战人员生成的Zcommand(component)传递给ZcommandCentre(remote object) 来处理该指令并等待一份执行结果。

ZcommandCentre维护了个系统的工作状态,不同的作战指令(Zcommand)在不同的系统工作状态下有着不同的处理方式,这一套系统规则形成了一个复杂的逻辑区(complex logic zone)

该逻辑区的信号传入与结果反馈正应为单元测试应实行的内容。故价构了TestMachine来测试ZfighterMachine与ZergCommandCentre的工作状态。

public class TestMachine extends TestCase {}

1. testSimpleCommand() 测试简单指令元素在不同系统状态下的执行结果。

2. testExtremeCondition() 测试ZergCommandCentre在极端环境下(能源不足、弹药不足、通讯干扰)的工作情况。

3. testAllCondition() 则测试所有种类的Command在所有condition下的执行结果与工作状况。

(备注:详见junitzerg.test.TestMachine.java,TestAll则批处理执行所有的测试)

6. SUMMARY & CONCLUSION

1.设计一个应当失败的测试。

2.勿用TestCase的Constructor初始化Fixtures,用setUp/tearDown。

3. 避免编写有副作用的TestCase。

4. 确保测试与时间无关,莫依赖使用过期的数据进行测试。

5. 尽可能利用JUnit提供的assertXXX/fail方法以及异常处理,使测试代码统一化。

6. 如果编写的软件面向国际市场,则编写测试时要考虑国际化的因素。

7. 无意间发现JUnit的作者包括Erich Gamma。

7. EXTENSION

1. 测试的关键是洞悉系统的复杂区域与不稳定区域,抽取其做测试。

2. 管理测试模块与系统本身模块,使其同步发展。

3. JUnit仅为一份单元测试的应用框架,集成测试的框架又会是何其。

4. 考察总结开发与测试并同的工作模式,以加快工程开发的运行效率。

乐晨光 2002-2-26

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有