




已阅读5页,还剩8页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
实验1:JUnit单元测试基础董瑞志常熟理工学院软件工程系实验目的理解手工编写单元测试的基本方法;编写简单的基于JUnit的单元测试用例;深入掌握JUnit的核心类、JUnit生命周期。课时安排8课时实验内容JUnit初步单元测试可以描述为“确保方法接收预期范围内的输入,并且对每个测试输入返回预期的结果。”单元测试是独立的一个工作单元(一个工作单元是一项任务,它不依赖于其他任何任务的完成)。在Java应用程序中,“独立的一个动作单元”常常指的是一个方法。1 编写Calculator类及其手工测试类TestCalculatorManual图1:手工测试Calculator单元测试的一条准则是“若程序的某项功能没有经过测试,那么该功能基本等于不存在”。这里的add方法是Calculator的核心功能之一,这里我们先手工编写测试类TestCalculatorManual。2 TestCalculatorManual的设计优化也许你想为Calculator添加其他方法如subtract或multiply,就需要对TestCalculatorOne进行模块化的优化:图2:优化手工测试的测试脚本3 用JUnit进行单元测试(1)JUnit有很多功能可以简化测试用例的编写和运行,我们编写Test CaseTestCalculatorWithJUnit如下。图3:使用JUnit设计测试脚本在Calculator类中添加subtract(), multiply(),divide()后,如何编写手工测试用例和基于JUnit框架的测试用例应该如何编写?(2)使用默认的TestSuite, 显式调用Junit TestRunner图4:显式调用Junit TestRunner/* 调用由TestRunner自动创建的TestSuite对象* 默认的TestSuite对象将扫描测试类,找出所有以test开头的方法,* 为每一个testXXX方法都创建一个TestCase实例。* 要调用的方法的名称会传给TestCase的构造函数,* 这样每个实例就拥有了一个独一无二的标示。*/public static TestSuite suite()return new TestSuite(TestCalculatorWithJunit.class);public static void main(String args) /junit.textui.TestRunner.run(TestCalculatorWithJunit.class);junit.swingui.TestRunner.run(TestCalculatorWithJunit.class);(3)创建TestAll缺省的TestSuite设计目的在于让测试人员可以轻松应对简单的测试情形。但是当要组合多个Suite,把它作为主Suite的一部分,特别是这些suite来自不同的包;或者要运行多个Suite、在一个Suite中选一些测试来执行等情况下,这就需要创建自己的suite对象。Junit Framework中,Test接口如下:public interface Test /* * Counts the number of test cases that will be run by this test. */public abstract int countTestCases();/* * Runs a test and collects its result in a TestResult instance. */public abstract void run(TestResult result);而TestSuite的addTest():public void addTest(Test test) fTests.addElement(test);即可以为TestSuite添加TestSuite也可以添加TestCase,这就为创建特殊的suite或者组合出TestAll创造了方便。通常情况下,TestAll仅仅包括一个静态的suite(),该方法会注册应用程序需要定期执行的所有Test对象(包括TestCase和TestSuite)。TestAll的suite()方法细节如下:public static Test suite()TestSuite suite=new TestSuite(All tests will be executed);suite.addTestSuite(TestCalculatorWithJunit.class);return suite;JUnit单元测试的步骤1 Junit三重唱当你需要编写更多的TestCase的时候,你可以创建更多的TestCase对象。当你需要一次执行多个TestCase对象的时候,您可以创建一个TestSuite对象或使用缺省的TestSuite对象进行封装。为了执行TestSuite,需要使用TestRunner。通过TestRunner的执行生成TestResult对象。(如图5所示)图5:JUnit成员三重唱,共同产生测试结果(1) TestCase测试用例用户定义的TestCase必须扩展junit.framework.TestCase类,它以testXXX方法的形式包含了一个或多个测试。一个测试用例把具有公共行为的测试归入一组。(2) TestSuite测试套装一个测试套装可以把多个测试用例或测试套装封装为一组(3) TestRunner测试运行器测试运行器用来运行测试套装,Junit提供良种典型的测试运行器:junit.swingui.TestRunner 和 junit.textui.TestRunner2JUnit核心类JUnit核心类及其简介如下表所示:表1:JUnit核心类3.JUnit单元测试的步骤(1) 重载setUp(),封装测试环境初始化及测试数据准备;(2) 设计测试方法,以testXXX命名。(3) 在测试方法中使用断言方法如assertEquals(),assertTrue()等。JUnit中断言方法如表2所示。(4) 设计测试套件,或使用缺省的测试套件,调用TestRunner执行测试脚本,生成测试结果;(5) 重载tearDown()析构测试环境,执行收尾动作表2:断言方法assertEquals(expected, actual) assertEquals(message, expected, actual) assertEquals(expected, actual, delta) - used on doubles or floats, where delta is the difference in precision assertEquals(message, expected, actual, delta) - used on doubles or floats, where delta is the difference in precision assertFalse(condition) assertFalse(message, condition) assertNotNull(object) assertNotNull(message, object) assertNotSame(expected, actual) assertNotSame(message, expected, actual) assertNull(object) assertNull(message, object) assertSame(expected, actual) assertSame(message, expected, actual) assertTrue(condition) assertTrue(message, condition)案例分析1三角形问题设计类Triangle及其测试类TestTriangle,其类图如图6所示。Triangle中包含三个属性borderA, borderB, borderC,一个构造函数,isTriangle()判断三角形三边是否构成三角形,isType()判断在输入的三边形成三角形的情况下所形成的三角形的具体类型:等边三角形、等腰三角形还是不等边三角形。图6:Triangle及其测试类TestTriangle类定义如下:(1) 重载setUp()方法,进行测试准备,封装测试的预期结果。(2) 定义测试方法testIsTriangle()和testIsType()(3) 在测试方法中使用断言(4) 定义suite()方法,使用缺省的TestSuitepublic static TestSuite suite()return new TestSuite(TestTriangle.class);(5) 通过缺省的TestSuite调用TestRunner生成测试结果。/调用SWING UI或TEXT UI执行测试/junit.textui.TestRunner.run(TestTriangle.class);junit.swingui.TestRunner.run(TestTriangle.class);2作业设计类NextDay,该类包含year, month, day三个属性,该类可以根据用户输入的year, month, day的值输出用户输入日期对应的下一天。设计NextDay的测试类TestNextDay对其中核心方法,综合使用等价类划分和健壮性测试方法设计测试用例执行单元测试。建议NextDay结构如图7所示。图7:NextDay3.测试Controller构件通过上述案例我们已经初步了解了JUnit单元测试的机制。现在我们将通过一个控制器构件的测试,讨论如何定义测试需求、设计测试用例、实现和执行测试脚本。控制器构件是一个常见的应用模式,它可以以多种方式出现在软件系统中,例如在Web应用中控制器构件接收HTTP请求、进行请求分发给适合的处理器构件。(1) 设计控制器构件按照控制器构件的规格说明:接收请求;对请求执行常用计算;选择合适的请求处理器;路由请求;可能会提供一个顶层的处理器用于处理错误或异常。鉴于此我们设计4个对象(如图8所示):Request, Response, RequestHandler, Controller。Controller接受Request,分发给RequestHandler,并返回Response对象。图8:测试对象控制器构件(2) 定义控制器构件的实现基类阅读JUnit in Action,按照图8编写DefaultController类;设计错误访问类ErrotResponse,如图9所示。图9:ErrorResponse(3) 0次迭代定义测试类框架,实例化DefaultController,此时测试方法定义为testMethod():public class TestDefaultController0 extends TestCase private DefaultController controller;/以setUp()为扩展点,实例化DefaultController对象protected void setUp()controller=new DefaultController();/首先定义新的测试方法,为了有测试可以运行public void testMethod()/*为暂时没有实现的测试代码抛出异常,这样避免了测试通过,*提醒必须实现其代码*/throw new RuntimeException(Implement me!);(4) 测试需求Controller的目的在于处理请求并响应,但是在处理请求之前必须首先设计添加RequestHandler来做实际的处理工作。所以要紧的是先测试是否可以添加RequestHandler。为了判断测试是否成功需要比较测试预期结果和实际执行结果。检查addHandler()发现:void addHandler(Request request, Response response)而DefaultController中getHandler()签名如下:RequestHandler getHandler(Request request)单元测试的要点在于一次只测试一个对象。为了创建单元测试必须两种对象:领域对象,代表被测试对象;测试对象,即和领域对象交互的对象,他们是测试领域对象的环境需求。在本轮迭代中,我们唯一用到的领域对象是DefaultController,其它都是测试对象。鉴于此,设计TestDefaultController1如下:增加一个RequestHandler,引用一个Request;获得一个RequestHandler判断传递的是否是同一个Request;检查获取的RequestHandler是否就是添加的那个。那么,把测试类放在何方?有两种可选方案,其一把测试类作为同一包中的公共类;其二,作为test case的内部类,如图10所示。图10:迭代1迭代1 TestDefaultController1的测试方法:public void testAddHandler()/实例化测试对象Request request=new TestRequest();RequestHandler handler=new TestHandler();/把待测试对象controller添加到合适的测试处理器controller.addHandler(request, handler);RequestHandler handler2=controller.getHandler(request);/监测读取的对象是否为刚刚传入的对象assertSame(handler2, handler);迭代2 TestDefaultController2:测试DefaultController的核心请求处理public void testProcessRequest()/创建测试对象,并添加测试处理器Request request=new TestRequest();RequestHandler handler=new TestHandler();controller.addHandler(request, handler);/调用processRequest()Response response=cessRequest(request);/验证reponse对象不是nullassertNotNull(Must not return a null response.,response);/把测试结果和预期的TestResponse对象进行比较assertEquals(TestResponse.class, response.getClass();迭代2代码重构TestDefaultController2Refact:分离初始化逻辑到setUp()TestDefaultController2Refact中定义属性:private Request request;private RequestHandler handler;setUp():protected void setUp()controller=new DefaultController();request=new TestRequest();handler=new TestHandler();controller.addHandler(request, handler);同时修改testAddHandler()和testProcessHandler()迭代3 TestDefaultControllerMockExceptionCond:模拟异常条件在TestDefaultControllerMockExceptionCond创建内部类TestExceptionHandler implements RequestHandlerprivate class TestHandler implements RequestHandlerpublic Response process(Request request) throws Exception return new TestResponse();定义测试方法testProcessRequestAnswerErrorResponse():public void testProcessRequestAnswerErrorResponse()TestRequest request=new TestRequest();TestExceptionHandler handler=new TestExceptionHandler();controller.addHandler(request, handler);Response response=cessRequest(request);assertNotNull(Must not return a null response, response);assertEquals(ErrorResponse.class, response.getClass();运行测试脚本,测试方法testProcessRequestAnswerErrorResponse()运行失败如图11所示,我们需要做两件事情:为测试请求换名,因为Fixture中已经有了一个叫做Test的请求;其次,需要在类中增加更多的异常处理代码,以免运行时候发生RuntimeException。 图11:testProcessRequestAnswerErrorResponse()运行失败迭代3代码优化:TestDefaultControllerMockExceptionCondEvolution定义TestDefaultControllerMockExceptionCondEvolution的内部类TestRequest implements Requestprivate static final String DEFAULT_NAME=Test;private String name;public TestRequest(String name)=name;public TestRequest()this(DEFAULT_NAME);public String getName()return ;重构TestDefaultControllerMockExceptionCondEvolution中的testProcessAnswerErrorResponse:public void testProcessRequestAnswerErrorResponse()TestRequest request=new TestRequest(testError);TestExceptionHandler handler=new TestExceptionHandler();controller.addHandler(request, handler);Response response=cessRequest(request);assertNotNull(Must not return a null response, response);assertEquals(ErrorResponse.class, response.getClass();迭代4 TestDefaultControllerException:测试异常测试异常情况如下:其一,测试请求处理器为定义异常;测试注册同名请求异常。在TestDefaultControllerException添加测试方法testGetHandlerNotDefined()和testAddRequestDuplicateName()。public void testGetHandlerNotDefined()TestRequest request=new TestRequest(testNotDefined);tryfail(An exception shold be raised if the request
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 安徽艺术职业学院《房屋建筑识图仿真实训》2023-2024学年第二学期期末试卷
- 山东中医药大学《编排设计》2023-2024学年第二学期期末试卷
- 广东舞蹈戏剧职业学院《nux系统与大数据应用》2023-2024学年第二学期期末试卷
- 郑州商贸旅游职业学院《营销效果评估与分析》2023-2024学年第二学期期末试卷
- 西安科技大学高新学院《剧目与舞台表演》2023-2024学年第二学期期末试卷
- 湖南信息职业技术学院《外国人文经典(下)》2023-2024学年第二学期期末试卷
- 内蒙古工业职业学院《创业实训》2023-2024学年第二学期期末试卷
- 广西职业技术学院《数据库原理与应用(双语)》2023-2024学年第二学期期末试卷
- 甘肃财贸职业学院《工程会计》2023-2024学年第二学期期末试卷
- 成都农业科技职业学院《环境影响评价A》2023-2024学年第二学期期末试卷
- 计算机应用技术毕业论文-计算机应用技术论文5000字
- 《学弈》公开课课件完整版
- 手写通用收款收据word模板
- 2022 CSCO肝癌诊疗指南
- GB/T 4744-1997纺织织物抗渗水性测定静水压试验
- GB/T 17911-2006耐火材料陶瓷纤维制品试验方法
- GB/T 14206-2005玻璃纤维增强聚酯波纹板
- 人教版PEP英语四年级下册Unit-5-my-clothes-B-read-and-write课件
- 自治区促进就业创业政策课件
- 陶瓷制作工艺知识课件
- 重组人生长激素在儿科临床的应用课件
评论
0/150
提交评论